国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

flutter開(kāi)發(fā)實(shí)戰(zhàn)-video_player插件播放抖音直播實(shí)現(xiàn)(僅限Android端)

這篇具有很好參考價(jià)值的文章主要介紹了flutter開(kāi)發(fā)實(shí)戰(zhàn)-video_player插件播放抖音直播實(shí)現(xiàn)(僅限Android端)。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問(wèn)。

flutter開(kāi)發(fā)實(shí)戰(zhàn)-video_player插件播放抖音直播實(shí)現(xiàn)(僅限Android端)

在之前的開(kāi)發(fā)過(guò)程中,遇到video_player播放視頻,通過(guò)查看video_player插件描述,可以看到video_player在Android端使用exoplayer,在iOS端使用的是AVPlayer。由于iOS的AVPlayer不支持flv、m3u8格式的直播,這里video_player播放抖音直播僅僅在Android有效,在iOS端,如果需要播放抖音直播,可以使用fijkplayer插件進(jìn)行播放,由于fijkplayer使用的是ijkplayer,可以播放flv、m3u8格式的直播。

一、引入

在pubspec.yaml中引入video_player

  # 播放器
  video_player: ^2.7.0
  # fijkplayer: ^0.11.0

二、實(shí)現(xiàn)VideoPlayer的Widget

2.1 在iOS中的設(shè)置

在iOS工程中info.plist添加一下設(shè)置,以便支持Https,HTTP的視頻地址

<key>NSAppTransportSecurity</key>
<dict>
	<key>NSAllowsArbitraryLoads</key>
	<true/>
</dict>

2.2 在Android中的設(shè)置

需要在/android/app/src/main/AndroidManifest.xml文件中添加網(wǎng)絡(luò)權(quán)限

<uses-permission android:name="android.permission.INTERNET"/>

2.3 播放的VideoPlayer

使用video_player插件,需要使用VideoPlayerController來(lái)控制播放、暫停、添加監(jiān)聽(tīng)

初始化后添加監(jiān)聽(tīng),來(lái)獲取VideoPlayerController中的Value值,可以看到一些狀態(tài)。例如

VideoPlayerValue(duration: 0:00:00.001000, size: Size(1280.0, 720.0), position: 0:32:14.877000, caption: Caption(number: 0, start: 0:00:00.000000, end: 0:00:00.000000, text: ), captionOffset: 0:00:00.000000, buffered: [DurationRange(start: 0:00:00.000000, end: 0:32:17.868000)], isInitialized: true, isPlaying: true, isLooping: false, isBuffering: false, volume: 1.0, playbackSpeed: 1.0, errorDescription: null, isCompleted: false)

添加監(jiān)聽(tīng)

// 添加監(jiān)聽(tīng)
  void addListener() {
    if (_controller != null) {
      _controller!.addListener(videoListenerCallback);
    }
  }

移除監(jiān)聽(tīng)

// 移除監(jiān)聽(tīng)
  void removeListener() {
    if (_controller != null) {
      _controller!.removeListener(videoListenerCallback);
    }
  }

監(jiān)聽(tīng)的callback回調(diào)

void videoListenerCallback() {
    // 監(jiān)聽(tīng)結(jié)果
    if (_controller != null) {
      if (_controller!.value.hasError) {
        // 出現(xiàn)錯(cuò)誤
        setState(() {});
      }

      if (_controller!.value.isCompleted) {
        // 直播完成
        setState(() {});
      }

      if (_controller!.value.isBuffering) {
        // 正在buffer
      }

      if (_controller!.value.hasError || _controller!.value.isCompleted) {
        // 是否處于錯(cuò)誤狀態(tài) 或者 播放完成
        if (widget.liveController.onOutLinkPlayerCompleted != null) {
          widget.liveController.onOutLinkPlayerCompleted!();
        }
      }

      if (_controller!.value.hasError == false) {
        // 可播放,隱藏封面
        if (widget.liveController.onOutLinkPlayerCanPlay != null) {
          widget.liveController.onOutLinkPlayerCanPlay!();
        }
      }
    }
  }

播放

Future<void> play() async {
if (_controller != null) {
	await _controller?.play();
    }
}

暫停

Future<void> play() async {
if (_controller != null) {
	await _controller?.pause();
    }
}

完整代碼如下

//  視頻播放測(cè)試
class VideoPlayerSkeleton extends StatefulWidget {
  const VideoPlayerSkeleton({
    Key? key,
    required this.videoUrl,
    required this.isLooping,
    this.autoPlay = true,
    required this.width,
    required this.height,
  }) : super(key: key);

  final String videoUrl;
  final bool isLooping;
  final bool autoPlay;
  final double width;
  final double height;

  
  State<VideoPlayerSkeleton> createState() => _VideoPlayerSkeletonState();
}

class _VideoPlayerSkeletonState extends State<VideoPlayerSkeleton> {
  VideoPlayerController? _controller;

  
  void initState() {
    super.initState();

    videoPlay();
    print("_VideoPlayerSkeletonState videoUrl:${widget.videoUrl}");
  }

  // 添加監(jiān)聽(tīng)
  void addListener() {
    if (_controller != null) {
      _controller!.addListener(videoListenerCallback);
    }
  }

  void videoListenerCallback() {
    // 監(jiān)聽(tīng)結(jié)果
    if (_controller != null) {
      if (_controller!.value.hasError) {
        // 出現(xiàn)錯(cuò)誤
        setState(() {});
      }

      if (_controller!.value.isCompleted) {
        // 直播完成
        setState(() {});
      }

      if (_controller!.value.isBuffering) {
        // 正在buffer
      }
    }
  }

  // 移除監(jiān)聽(tīng)
  void removeListener() {
    if (_controller != null) {
      _controller!.removeListener(videoListenerCallback);
    }
  }

  // 播放視頻
  Future<void> videoPlay() async {
    _controller?.dispose();

    _controller = VideoPlayerController.networkUrl(
      Uri.parse(widget.videoUrl),
      videoPlayerOptions: VideoPlayerOptions(
        mixWithOthers: true,
        allowBackgroundPlayback: false,
      ),
    );

    addListener();

    await _controller?.initialize().then((_) {
      // Ensure the first frame is shown after the video is initialized, even before the play button has been pressed.
      setState(() {});
    }).catchError((error) {
      // 是否處于錯(cuò)誤狀態(tài) 或者 播放完成
      if (widget.liveController.onOutLinkPlayerCompleted != null) {
        widget.liveController.onOutLinkPlayerCompleted!();
      }
    }).whenComplete(() {
      // print('checkAnimationTimeout whenComplete');
    });

    await _controller!.setLooping(widget.isLooping);
    if (widget.autoPlay) {
      await _controller?.play();
    } else {
      await _controller?.pause();
    }
  }

  
  Widget build(BuildContext context) {
    return Container(
      width: widget.width,
      height: widget.height,
      color: Colors.black87,
      child: Stack(
        alignment: Alignment.center,
        children: [
          buildVideoPlayer(context),
          buildStateIntro(context),
        ],
      ),
    );
  }

  // 播放視頻
  Widget buildVideoPlayer(BuildContext context) {
    if (_controller != null && _controller!.value.isInitialized) {
      return AspectRatio(
        aspectRatio: _controller!.value.aspectRatio,
        child: VideoPlayer(_controller!),
      );
    }
    return Container();
  }

  // 播放過(guò)程中出現(xiàn)error
  Widget buildStateIntro(BuildContext context) {
    if (_controller != null) {
      String title = "";
      String message = "";
      bool showIntro = false;
      if (_controller!.value.hasError) {
        showIntro = true;
        title = "播放出現(xiàn)錯(cuò)誤";
        message = _controller!.value.errorDescription ?? "";
      } else {
        if (_controller!.value.isCompleted) {
          showIntro = true;
          title = "播放結(jié)束";
        }
      }

      if (showIntro) {
        return Container(
          padding: EdgeInsets.symmetric(vertical: 50.r, horizontal: 50.r),
          color: Colors.transparent,
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            crossAxisAlignment: CrossAxisAlignment.center,
            children: [
              Expanded(child: Container()),
              Text(
                title,
                textAlign: TextAlign.center,
                softWrap: true,
                style: TextStyle(
                  fontSize: 28.r,
                  fontWeight: FontWeight.w500,
                  fontStyle: FontStyle.normal,
                  color: Colors.white,
                  decoration: TextDecoration.none,
                ),
              ),
              SizedBox(
                height: 25.r,
              ),
              Text(
                message,
                textAlign: TextAlign.center,
                softWrap: true,
                style: TextStyle(
                  fontSize: 22.r,
                  fontWeight: FontWeight.w500,
                  fontStyle: FontStyle.normal,
                  color: Colors.white,
                  decoration: TextDecoration.none,
                ),
              ),
              Expanded(child: Container()),
            ],
          ),
        );
      }
    }

    return Container();
  }

  
  void dispose() {
    // TODO: implement dispose
    removeListener();
    _controller?.dispose();
    super.dispose();
  }
}

三、從抖音網(wǎng)站上找到直播地址

由于使用抖音播放地址,這里簡(jiǎn)單描述一下從抖音網(wǎng)站上找到直播的flv地址。

進(jìn)入抖音直播間,在網(wǎng)頁(yè)點(diǎn)擊鼠標(biāo)右鍵,看到檢查。
https://live.douyin.com/567752440034
flutter開(kāi)發(fā)實(shí)戰(zhàn)-video_player插件播放抖音直播實(shí)現(xiàn)(僅限Android端),移動(dòng)開(kāi)發(fā),flutter開(kāi)發(fā)實(shí)戰(zhàn),flutter,flutter,android,cocoa,抖音直播,video_player,exoplayer,avplayer

找到網(wǎng)絡(luò),刷新頁(yè)面,可以看到stream的一條,
flutter開(kāi)發(fā)實(shí)戰(zhàn)-video_player插件播放抖音直播實(shí)現(xiàn)(僅限Android端),移動(dòng)開(kāi)發(fā),flutter開(kāi)發(fā)實(shí)戰(zhàn),flutter,flutter,android,cocoa,抖音直播,video_player,exoplayer,avplayer

復(fù)制地址即可,使用該地址播放直播
flutter開(kāi)發(fā)實(shí)戰(zhàn)-video_player插件播放抖音直播實(shí)現(xiàn)(僅限Android端),移動(dòng)開(kāi)發(fā),flutter開(kāi)發(fā)實(shí)戰(zhàn),flutter,flutter,android,cocoa,抖音直播,video_player,exoplayer,avplayer

https://pull-hs-spe-f5.douyincdn.com/fantasy/stream-728687306789918920718_sd.flv?_neptune_token=MIGlBAxGexWdmRAYAAGs67QEgYIZi9nqbdY3bbfeK9dCVFBnlFTJNF1WNGRZ3AVrQ1ixrE_54JzkGsfuBjGER_2RhP5Qy_GzELSQuct4bK5aktJ2P2xnNznJG87KKhybkeCuefBAkOCI9Tx8eA1mz2GcmfcfqFNeR8DFPDcbzFp_sKyyJRnytmILegqrqjcjxgW04GYwBBDMFIKjhmF1jpi96O53wH7v&expire=1696731973&sign=38f51d46dcd5828fdbc212372bbb3522&volcSecret=38f51d46dcd5828fdbc212372bbb3522&volcTime=1696731973

四、查看直播結(jié)果

之后,我們將地址復(fù)制到VideoPlayerSkeleton中,運(yùn)行后,可以看到播放的效果

flutter開(kāi)發(fā)實(shí)戰(zhàn)-video_player插件播放抖音直播實(shí)現(xiàn)(僅限Android端),移動(dòng)開(kāi)發(fā),flutter開(kāi)發(fā)實(shí)戰(zhàn),flutter,flutter,android,cocoa,抖音直播,video_player,exoplayer,avplayer

注意:直接在Container上設(shè)置大小后,child是AspectRatio(
aspectRatio: _controller!.value.aspectRatio,
child: VideoPlayer(_controller!),
);
會(huì)出現(xiàn)畫(huà)面變形,可以使用Stack嵌套一下。

五、小結(jié)

flutter開(kāi)發(fā)實(shí)戰(zhàn)-video_player插件播放抖音直播實(shí)現(xiàn)(僅限Android端)。描述可能不是特別準(zhǔn)確,請(qǐng)見(jiàn)諒。

https://blog.csdn.net/gloryFlow/article/details/133634186

學(xué)習(xí)記錄,每天不停進(jìn)步。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-743226.html

到了這里,關(guān)于flutter開(kāi)發(fā)實(shí)戰(zhàn)-video_player插件播放抖音直播實(shí)現(xiàn)(僅限Android端)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來(lái)自互聯(lián)網(wǎng)用戶(hù)投稿,該文觀(guān)點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • Flutter 視頻video_player與緩存flutter_cache_manager

    參考官方DefaultCacheManager代碼,這里引入Config可以指定天數(shù)與最大個(gè)數(shù). 文件名 video_cache.dart 使用 await MyDefaultCacheManager().getSingleFile(url)) 即可

    2024年02月07日
    瀏覽(19)
  • Flutter:文件讀取—— video_player、chewie、image_picker、file_picker

    Flutter:文件讀取—— video_player、chewie、image_picker、file_picker

    簡(jiǎn)單學(xué)習(xí)一下幾個(gè)比較好用的文件讀取庫(kù) 簡(jiǎn)介 用于視頻播放 官方文檔 https://pub-web.flutter-io.cn/packages/video_player 安裝 加載網(wǎng)絡(luò)視頻 加載本地視頻 設(shè)置倍速和進(jìn)度條 video_player 雖然是官方提供的插件,但是很明顯它只適合拿來(lái)簡(jiǎn)單的播放視頻,就比如前端的 video 標(biāo)簽功能也很

    2024年02月13日
    瀏覽(87)
  • vue 視頻播放插件vue-video-player自定義樣式、自動(dòng)播放設(shè)置、設(shè)置一開(kāi)始全屏播放視頻

    vue 視頻播放插件vue-video-player自定義樣式、自動(dòng)播放設(shè)置、設(shè)置一開(kāi)始全屏播放視頻

    1、背景 項(xiàng)目中有涉及視頻播放的需求,并且UI設(shè)計(jì)了樣式,與原生的視頻video組件有差異,所以使用了vue-video-player插件,并對(duì)vue-video-player進(jìn)行樣式改造,自定義播放暫停按鈕、全屏按鈕、時(shí)間進(jìn)度條樣式等,自動(dòng)播放設(shè)置、設(shè)置一開(kāi)始全屏播放視頻、監(jiān)聽(tīng)全屏事件等。 2、效

    2024年02月05日
    瀏覽(25)
  • vue 視頻播放插件vue-video-player自定義樣式、自動(dòng)播放設(shè)置、設(shè)置一開(kāi)始全屏播放視頻、監(jiān)聽(tīng)全屏事件

    vue 視頻播放插件vue-video-player自定義樣式、自動(dòng)播放設(shè)置、設(shè)置一開(kāi)始全屏播放視頻、監(jiān)聽(tīng)全屏事件

    1、背景 項(xiàng)目中有涉及視頻播放的需求,并且UI設(shè)計(jì)了樣式,與原生的視頻video組件有差異,所以使用了vue-video-player插件,并對(duì)vue-video-player進(jìn)行樣式改造,自定義播放暫停按鈕、全屏按鈕、時(shí)間進(jìn)度條樣式等,自動(dòng)播放設(shè)置、設(shè)置一開(kāi)始全屏播放視頻、監(jiān)聽(tīng)全屏事件等。 2、效

    2024年02月08日
    瀏覽(29)
  • Unity視頻播放之Video Player的簡(jiǎn)單使用

    Unity視頻播放之Video Player的簡(jiǎn)單使用

    使用Unity自帶的VideoPlayer來(lái)播放視頻 一、準(zhǔn)備視頻 Unity3D常用視頻格式:.mov、.mpg、.mpeg、.mp4、.avi、.asf 如果都不識(shí)別,試試轉(zhuǎn)換成ogv格式。轉(zhuǎn)換完成之后,將視頻素材文件拖入U(xiǎn)nity Assets 文件夾內(nèi)。 二、創(chuàng)建UI及添加組件 創(chuàng)建RenderTexture資源,設(shè)置分辨率,跟視頻分辨率一致

    2024年01月18日
    瀏覽(41)
  • Unity2020Video player發(fā)布后無(wú)法播放視頻問(wèn)題

    我也是小白,用Unity過(guò)程中也是遇到很多草蛋問(wèn)題,我在做demo的時(shí)候第一次用到Unity的video player,聽(tīng)說(shuō)ogv格式能直接播放,我就把視頻轉(zhuǎn)了ogv格式,然后放到clip里,編輯器里運(yùn)行完全沒(méi)問(wèn)題,發(fā)布打包后就播放不了,黑屏都沒(méi)有,直接視頻沒(méi)了,百度搜的絕對(duì)路徑說(shuō)是放到

    2024年02月15日
    瀏覽(26)
  • 前端實(shí)現(xiàn)視頻播放功能----vue-video-player --save

    前端實(shí)現(xiàn)視頻播放功能----vue-video-player --save

    步驟一: npm安裝插件 : npm install vue-video-player --save 如果報(bào)錯(cuò) 安裝具體版本 如下所示: npm install --save vue-video-player@4.0.6 ?如果package.json文件內(nèi)顯示則為安裝成功 步驟二: 局部引入---這里因?yàn)橹挥幸粋€(gè)頁(yè)面需要所有采用的局部引入 在需要的頁(yè)面引入(這里注意路徑不要寫(xiě)錯(cuò)

    2024年02月10日
    瀏覽(28)
  • 【vue】 vue 實(shí)現(xiàn)視頻播放 vue-video-player

    【vue】 vue 實(shí)現(xiàn)視頻播放 vue-video-player

    注:用來(lái)測(cè)試的在線(xiàn)視頻url地址 1.下載依賴(lài) vue2 推薦下載指定版本依賴(lài),不然可能下載不下來(lái)報(bào)錯(cuò)。 2.全局注冊(cè)main.js 3.新建vue文件 下班`

    2024年02月16日
    瀏覽(25)
  • vue-video-player,springboot實(shí)現(xiàn)視頻分段下載播放

    vue-video-player,springboot實(shí)現(xiàn)視頻分段下載播放

    事情的起因是在博主把項(xiàng)目部署到服務(wù)器上后,發(fā)現(xiàn)由于視頻太大,加上服務(wù)器太垃圾,導(dǎo)致稍微大點(diǎn)的視頻加載很久才能播放(指十多分鐘…),然后就上網(wǎng)查找資料,看下咋實(shí)現(xiàn)。 這里涉及到有關(guān)http請(qǐng)求的知識(shí)“HTTP Header里的Range和Content-Range參數(shù),Range是在請(qǐng)求頭里 Ra

    2023年04月13日
    瀏覽(57)
  • Unity播放帶Alpha通道的視頻【W(wǎng)ebM+Video Player】(替代播放GIF方案)

    Unity播放帶Alpha通道的視頻【W(wǎng)ebM+Video Player】(替代播放GIF方案)

    在Unity中播放GIF或者動(dòng)態(tài)效果,可以通過(guò)Video Player播放帶透明通道的WebM視頻來(lái)實(shí)現(xiàn)。 制作帶Alpha的MOV視頻 制作帶Alpha通道的MOV視頻有多重方式,如AE、PR、PS等等,具體制作過(guò)程可以自行百度。 將MOV視頻格式轉(zhuǎn)化為WebM格式 將WebM格式導(dǎo)入U(xiǎn)nity,設(shè)置視頻播放 完成動(dòng)態(tài)效果展示

    2024年02月13日
    瀏覽(26)

覺(jué)得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包