Flutter ビデオ デコーダー fijkplayer の使用

       ビデオ監視プロジェクトに取り組んでいたとき、ビデオ ストリームをクライアントに表示する必要がありました. 最初は flutter に付属の VideoPlayer を使用して監視ビデオを再生しました. 最初は何の問題も見つかりませんでした, Androidエミュレーターが主に使用され、isoは一度も使用されていないため. シミュレーターまたは実機でテストを実行できるかどうか, 開発が終わりに近づくまで, iOSシミュレーターでテストすると問題が見つかります.ビデオストリームの場合H264だと普通に再生できますが、ビデオストリームがH265だと回転しっぱなしですシミュレータと実機は再生できません(Androidエミュレータと実機の両方が再生できます)。後で、再生を調整するためにサードパーティのプラグインに変更する予定でした。

  1. 参照されている fijkplayer プラグインを pubspec.yaml にインポートします
     # 视频解码器 软解码
      fijkplayer: ^0.10.1
  2. 詳細なステータス
    州名 プレーヤーのパフォーマンス
    アイドル アイドル状態、構築が完了したばかりの FijkPlayer がこの状態にあります。
    この状態では、プレーヤーは少量のメモリを占有し、追加のスレッドは開始されません。
    アイドル状態は、setDataSource を介してのみ初期化状態に変換できます
    初期化された アイドル状態と比較して、初期化完了状態には、入力メディア データ ソースに関する情報のみが含まれます。また、追加のスレッドは開かれません。
    async準備中 非同期の準備状態。この状態に到達するには、初期化された状態で prepareAsync を呼び出します。
    これは定常状態ではありません。この状態は、特定のタスクが完了するのを待ってから、準備済み状態に自動的に移行します。
    この状態での主な準備作業は、メディア ファイルの種類を検出し、メディア ファイルを開き、デコーダを開いて新しいデコード スレッドを作成し、新しいデータ読み取りスレッドを作成し、オーディオ出力デバイスを開き、新しいビデオ出力スレッドを作成することです。など
    準備 asyncPreparing は、指定されたタスクを完了すると、この状態に自動的に移行します。
    この状態では、オーディオとビデオのデータの一部がバッファリングされ、デコードされており、いつでも再生できます。
    始めました メディア (ビデオ、オーディオ) が再生されています。
    一時停止 メディア (ビデオ、オーディオ) の再生が一時停止しました。
    完了 メディア(ビデオ、オーディオ)の再生が完了しました。再生を最初からやり直すことができます。
    停止 プレーヤーのさまざまなスレッドが占有していたリソースが解放されました。オーディオ デバイスがオフになっています。
    終わり 手動で解放する必要があるプレーヤー内のすべてのメモリが解放されました。
    この状態のプレーヤーは、ガベージ コレクションがメモリを解放するのを待つことしかできません。
    エラー プレーヤーでエラーが発生しました。

  3. 簡単な使用コードは次のとおりです。
    import 'package:fijkplayer/fijkplayer.dart';
    import 'package:flutter/material.dart';
    
    class VideoScreen extends StatefulWidget {
      final String url;//视频地址
    
      VideoScreen({@required this.url});
    
      @override
      _VideoScreenState createState() => _VideoScreenState();
    }
    
    class _VideoScreenState extends State<VideoScreen> {
      final FijkPlayer player = FijkPlayer();
    
      _VideoScreenState();
    
      @override
      void initState() {
        super.initState();
        //传入视频地址,视频是否自动播放
        player.setDataSource(widget.url, autoPlay: true);
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
            appBar: AppBar(title: Text("视频监控")),
            body: Container(
              alignment: Alignment.center,
              child: FijkView(
                player: player,
              ),
            ));
      }
    
      @override
      void dispose() {
        super.dispose();
        player.release();
      }
    }
     
  4. 使用後は正常にプレイできますが、UI インターフェースが見づらかったり、自分で使用するには機能が不足していたり​​、さらに多くの機能が必要であることに気付いたりしても、心配する必要はありません。サードパーティ プロバイダーは長い間このことを考えてきたので、独自にカスタマイズできる UI インターフェイス設定を提供しています。panelBuilder を変更して UI インターフェイスを変更する必要がありますが、それほどナンセンスではなく、コードをアップロードする必要があります。最初にカスタムUI インターフェース コードを追加します
    class CustomFijkPanel extends StatefulWidget {
      final FijkPlayer player;
      final BuildContext buildContext;
      final Size viewSize;
      final Rect texturePos;
    
      const CustomFijkPanel({
        @required this.player,
        this.buildContext,
        this.viewSize,
        this.texturePos,
      });
    
      @override
      _CustomFijkPanelState createState() => _CustomFijkPanelState();
    }
    
    class _CustomFijkPanelState extends State<CustomFijkPanel> {
    
      FijkPlayer get player => widget.player;
      bool _playing = false;
    
      @override
      void initState() {
        super.initState();
        widget.player.addListener(_playerValueChanged);
      }
    
      void _playerValueChanged() {
        FijkValue value = player.value;
    
        bool playing = (value.state == FijkState.started);
        if (playing != _playing) {
          setState(() {
            _playing = playing;
          });
        }
      }
    
      @override
      Widget build(BuildContext context) {
        Rect rect = Rect.fromLTRB(
            max(0.0, widget.texturePos.left),
            max(0.0, widget.texturePos.top),
            min(widget.viewSize.width, widget.texturePos.right),
            min(widget.viewSize.height, widget.texturePos.bottom));
    
        return Positioned.fromRect(
          rect: rect,
          child: Container(
            alignment: Alignment.bottomLeft,
            child: IconButton(
              icon: Icon(
                _playing ? Icons.pause : Icons.play_arrow,
                color: Colors.white,
              ),
              onPressed: () {
                _playing ? widget.player.pause() : widget.player.start();
              },
            ),
          ),
        );
      }
    
      @override
      void dispose() {
        super.dispose();
        player.removeListener(_playerValueChanged);
      }
    }

        使用時のコードはこちら

FijkView(
  player: player,
  panelBuilder: (FijkPlayer player, FijkData data, BuildContext context, Size viewSize, Rect texturePos) {
    return CustomFijkPanel(
      player: player,
      buildContext: context,
      viewSize: viewSize,
      texturePos: texturePos);
  },
)

ここで行われます。単純な使用、カスタム使用、詳細を確認する必要がある場合は、公式ドキュメントを参照してください。アドレスは次のとおりです

おすすめ

転載: blog.csdn.net/as425017946/article/details/127124281