首頁 > 軟體

詳解Flutter中視訊播放器外掛的使用教學

2022-02-28 16:00:06

您已經看到很多包含視訊內容的應用程式,比如帶有視訊教學的食譜應用程式、電影應用程式和體育相關的應用程式。您是否想知道如何將視訊內容新增到您的下一個Flutter應用程式中?

從頭開始實現視訊功能將是一項繁重的任務。但有幾個外掛可以讓開發者的生活變得輕鬆。視訊播放器外掛是可用於 Flutter 的最佳外掛之一,可滿足這一要求。

在這篇文章中,您將學習如何應用視訊播放器外掛以及控制視訊播放器的不同功能。
我們將討論這些主題。

  • 建立一個新的視訊播放器
  • 新增播放和暫停按鈕
  • 建立一個快進
  • 新增一個視訊進度指示器
  • 應用視訊的字幕

建立一個新的視訊播放器

在使用視訊播放器外掛之前,你應該把它新增到你的pubspec.yaml 檔案中。當你開啟pubspec.yaml 檔案時,你可以看到執行你的應用程式所需的一些設定和依賴性。我們的視訊播放器外掛應該被新增到dependencies 塊下。

dependencies:
  flutter:
    sdk: flutter
  cupertino_icons: ^1.0.2
  video_player: 2.1.15  //video player

該外掛的當前版本是2.1.15 ,但你可以通過檢視外掛頁面在這裡新增最新版本。如果你儲存檔案時是在VS Code中,它會自動下載該外掛。如果不是,開啟終端,寫flutter pub get 來下載該外掛。

進入你想新增該外掛的檔案,並匯入video_player.dart 檔案。

import 'package:video_player/video_player.dart';

現在你可以在你的專案中使用視訊播放器外掛了。

有幾種方法來載入視訊。讓我們從資產中載入我們的例子。在專案的根層建立一個assets/video資料夾,在該資料夾內新增一個視訊。然後在pubspec.yaml ,在assets 部分,指定檔案路徑,如下所示。

assets:
    - assets/video/video.mp4

讓我們建立一個單獨的有狀態的部件,稱為VideoPlayerWidget ,以插入我們的視訊播放器相關的實現。

你可以在initState 方法中初始化視訊播放器,如下所示。另外,別忘了dispose ,讓視訊播放器做清理工作。

class _VideoPlayerState extends State<VideoPlayerWidget> {
  late VideoPlayerController _videoPlayerController;
  @override
  void initState() {
    super.initState();
    _videoPlayerController = VideoPlayerController.asset(
        'assets/video/video.mp4')
      ..initialize().then((_) {
        setState(() {});
        _videoPlayerController.play();
      });
  }

  @override
  void dispose() {
    _videoPlayerController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Center(
      child: VideoPlayer(_videoPlayerController),
    );
  }
}

VideoPlayerController 必須用late 關鍵字來指定,因為我們在這一行中仍然沒有定義視訊播放器控制器,我們將在後面做這個。在initState 裡面,videoPlayerController 已經和資產的路徑一起被初始化。

當初始化完成後,它改變了狀態並重建了小部件。你可以在初始化後開始播放視訊。

取代assets ,你可以使用視訊的URL。為了存取網路,你應該給Android和iOS新增網際網路許可權設定。

從根目錄下,進入ios/Runner ,開啟info.plist 檔案。然後,在該檔案中新增以下設定。

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

接下來,去android/app/src/main ,並開啟AndroidManifest.xml 。然後,向其新增以下程式碼。

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

現在你可以把asset 改為network ,並在那裡新增視訊URL。

  @override
  void initState() {
    super.initState();
    _videoPlayerController =
        VideoPlayerController.network('video_url_here')
          ..initialize().then((_) {
            setState(() {});
            _videoPlayerController.play();
          });
  }

即使初始化已經完成,也應該有辦法在使用者介面中顯示播放器。VideoPlayer widget可以用來做到這一點。為了使它工作,你應該把控制器作為第一個引數傳遞給VideoPlayer widget。

在顯示VideoPlayer widget之前,最好先檢查初始化是否成功。

  @override
  Widget build(BuildContext context) {
    return Center(
      child: _videoPlayerController.value.isInitialized ? VideoPlayer(_videoPlayerController) : Container(),
    );
  }

現在你可以看到螢幕上的視訊了。但是有一個小問題:它的長寬比不合適。這可以通過使用AspectRatio widget來解決。視訊播放器提供了一個適當的視訊長寬比,你可以使用這個值來設定為AspectRatio widget。

  @override
  Widget build(BuildContext context) {
    return Center(
      child: _videoPlayerController.value.isInitialized ? AspectRatio(aspectRatio: 
      _videoPlayerController.value.aspectRatio,
      child: VideoPlayer(_videoPlayerController)
      ) : Container(),
    );
  }

現在你可以看到具有適當長寬比的視訊。

新增播放和暫停按鈕

首先,讓我們把視訊播放器小部件包在一個列小部件裡面,因為我們應該把播放和暫停按鈕放在播放器下面。在播放器小元件之後的列內,讓我們在一個Row 小元件內新增兩個ElevatedButton 小元件,在這些按鈕之間讓我們新增一個Padding 小元件以保持一些呼吸空間。

對每個ElevatedButton ,新增相關的Icons ,作為子部件。然後在播放按鈕onPressed 的回撥裡面,你可以參考_videoPlayerController ,並呼叫play 方法來開始播放視訊。在暫停按鈕裡面,使用pause 方法而不是播放。

現在你可以刪除之前在initState 方法裡面新增的播放。

  @override
  Widget build(BuildContext context) {
    return Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: [
        _videoPlayerController.value.isInitialized ? AspectRatio(aspectRatio: 
        _videoPlayerController.value.aspectRatio,
        child: VideoPlayer(_videoPlayerController)
        ) : Container(),
        Row(
          mainAxisAlignment: MainAxisAlignment.center, 
          children: [

            ElevatedButton(onPressed: (){
              _videoPlayerController.pause();
            }, child: Icon(Icons.pause)),
              Padding(padding: EdgeInsets.all(2)),
             ElevatedButton(onPressed: (){
              _videoPlayerController.play();
            }, child: Icon(Icons.play_arrow))
          ],
        )
      ],
    );
  }

另外,你可以給按鈕新增樣式,得到一個看起來很圓的按鈕,這通常是在視訊播放器中。

 @override
  Widget build(BuildContext context) {
    return Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: [
        _videoPlayerController.value.isInitialized
            ? AspectRatio(
                aspectRatio: _videoPlayerController.value.aspectRatio,
                child: VideoPlayer(_videoPlayerController))
            : Container(),
        Padding(
          padding: EdgeInsets.all(20),
        ),
        Row(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            ElevatedButton(
                style: ButtonStyle(
                    backgroundColor: MaterialStateProperty.all<Color>(Colors.blue),
                    fixedSize: MaterialStateProperty.all(Size(70, 70)),
                    shape: MaterialStateProperty.all(RoundedRectangleBorder(
                        borderRadius: BorderRadius.circular(100)))),
                onPressed: () {
                  _videoPlayerController.pause();
                },
                child: Icon(Icons.pause)),
            Padding(padding: EdgeInsets.all(2)),
            ElevatedButton(
                style: ButtonStyle(
                    backgroundColor: MaterialStateProperty.all<Color>(Colors.redAccent),
                    fixedSize: MaterialStateProperty.all<Size>(Size(80, 80)),
                    shape: MaterialStateProperty.all(RoundedRectangleBorder(
                        borderRadius: BorderRadius.circular(100)))),
                onPressed: () {
                  _videoPlayerController.play();
                },
                child: Icon(Icons.play_arrow))
          ],
        )
      ],
    );
  }

建立一個快進

在實現快進之前,讓我們思考一下我們需要什麼。首先,應該有一個存取當前視訊位置/時間的方法和一個設定新值的方法。控制器的seekTo 方法允許我們為視訊設定持續時間。

你可以通過視訊播放器value 屬性存取當前的視訊位置,就像下面這樣。

ElevatedButton(
       style: ButtonStyle(
          backgroundColor: MaterialStateProperty.all<Color>(Colors.blue),
          fixedSize: MaterialStateProperty.all(Size(70, 70)),
          shape: MaterialStateProperty.all(RoundedRectangleBorder(
              borderRadius: BorderRadius.circular(100)))),
                onPressed: () {
                  _videoPlayerController.seekTo(Duration(
                   seconds: _videoPlayerController.value.position.inSeconds + 10));
                },
                child: Icon(Icons.fast_forward))

像這樣,當用戶點選按鈕時,你也可以通過減少10 秒來實現向後倒轉。

新增一個視訊進度指示器

視訊播放器外掛提供了內建的功能來新增一個進度條以及一些控制元件。你可以使用VideoProgressIndicator widget來實現這個功能。

作為第一個引數,你必須傳遞控制器並設定allowScrubbing 屬性。allowScrubbing 屬性將允許使用者通過觸控小元件來滑動進度。通過啟用這個,使用者可以跳到視訊的不同時間戳。此外,你還可以單獨控制尋求欄的背景顏色、緩衝區顏色和播放區顏色。

VideoProgressIndicator(
          _videoPlayerController,
          allowScrubbing: true,
          colors: VideoProgressColors(
              backgroundColor: Colors.red,
              bufferedColor: Colors.black,
              playedColor: Colors.blueAccent),
        )

應用視訊的字幕

字幕對你的應用程式來說需要兩樣東西。第一個是不同時期的段落/單詞列表,第二個是在視訊播放時顯示這些標題的方法。為此,應該有一種方法來為時間變化新增一個監聽器。

視訊播放器包含一個addListener 方法,每秒鐘執行一次。你可以使用這個監聽器,根據不同的時間段為視訊播放器提供字幕。

首先,讓我們建立一個Map ,其中包含時間作為一個鍵,字幕文字作為一個值。在Map ,時間的單位將是秒。

Map<int,String> captions = {
    5:"First subtitle",
    20:"Second subtitle"
  };

接下來,在初始化視訊播放器時註冊一個Listener 。在回撥裡面,你可以檢查視訊是否正在播放,如果視訊正在播放,則獲得當前的時間為秒。然後,如果當前值包含在captions 地圖中,我們可以像下面這樣將該值設定為選定的標題。

void initState() {
    super.initState();
    _videoPlayerController =
        VideoPlayerController.asset('assets/video/video.mp4')
        ..addListener(() {
            if(_videoPlayerController.value.isPlaying){
              setState(() { 
                if(captions.containsKey(_videoPlayerController.value.position.inSeconds)){
              selectedCaption = captions[_videoPlayerController.value.position.inSeconds];                
                }
              });
            }
        })
          ..initialize().then((_) {
            setState(() {});
            _videoPlayerController.play();
          });
  }

現在你可以使用ClosedCaption 來設定那個選定的標題。你可以給標題文字新增一些樣式,以獲得更好的可見性。

 ClosedCaption(
     text: selectedCaption,textStyle: TextStyle(fontSize: 15,color: Colors.white),)

但是,每次標題改變時,建立主部件並不是好的做法。因此,我們應該把標題邏輯提取到一個單獨的小部件。

要註冊一個監聽器,你應該把視訊控制器傳遞給一個新建立的子部件。

從那裡,你可以在子部件內註冊監聽器。

class VCaption extends StatefulWidget {
  const VCaption(
     this.videoPlayerController,
  );
  final VideoPlayerController videoPlayerController;
  @override
  _VCaptionState createState() => _VCaptionState();
}
class _VCaptionState extends State<VCaption> {
  String? selectedCaption = "";
  Map<int,String> captions = {
    5:"First subtitle",
    20:"Second subtitle"
  };

  @override
  void initState() {
    widget.videoPlayerController.addListener(() {
      if(widget.videoPlayerController.value.isPlaying){
              print("Time ${widget.videoPlayerController.value.position.inSeconds}");
              setState(() { 
                if(captions.containsKey(widget.videoPlayerController.value.position.inSeconds)){
              selectedCaption = captions[widget.videoPlayerController.value.position.inSeconds];                
                }
              });
            }
    });
    super.initState();
  }
  @override
  Widget build(BuildContext context) {
    return ClosedCaption(
      text: selectedCaption,textStyle: TextStyle(fontSize: 15,color: Colors.white),);
  }
}

現在我們可以在之前建立的欄目內新增這個小部件,並將_videoPlayerController 作為引數傳遞。你可以在把小部件新增到樹上之前檢查視訊播放器是否已經被初始化,就像下面這樣。

 _videoPlayerController.value.isInitialized ? VCaption(_videoPlayerController) : Container(),

你可以使用Stack widget在視訊頂部顯示這些字幕,而不是在視訊下面顯示那些字幕。字幕以及進度指示器已經被移到了Stack widget裡面,以便在視訊的頂部顯示。

 Stack(
          children: [
            _videoPlayerController.value.isInitialized
                ? AspectRatio(
                    aspectRatio: _videoPlayerController.value.aspectRatio,
                    child: VideoPlayer(_videoPlayerController))
                : Container(),
            Positioned(
              bottom: 2,
              width: MediaQuery.of(context).size.width,
              child: _videoPlayerController.value.isInitialized
                  ? VCaption(_videoPlayerController)
                  : Container(),
            ),
            Positioned(
                bottom: 0,
                width: MediaQuery.of(context).size.width,
                child: VideoProgressIndicator(
                  _videoPlayerController,
                  allowScrubbing: false,
                  colors: VideoProgressColors(
                      backgroundColor: Colors.blueGrey,
                      bufferedColor: Colors.blueGrey,
                      playedColor: Colors.blueAccent),
                ))
          ],
        )

結論

使用視訊播放器外掛而不是從頭開始實現一個視訊播放器,可以節省大量的開發時間,並提供所有開箱即用的功能。

如果您想超越這些客製化,實現一個具有Material-和Cupertino靈感的漂亮的視訊播放器,您可以選擇chewie Flutter外掛

以上就是詳解Flutter中視訊播放器外掛的使用教學的詳細內容,更多關於Flutter視訊播放器外掛的資料請關注it145.com其它相關文章!


IT145.com E-mail:sddin#qq.com