ビデオ監視プロジェクトに取り組んでいたとき、ビデオ ストリームをクライアントに表示する必要がありました. 最初は flutter に付属の VideoPlayer を使用して監視ビデオを再生しました. 最初は何の問題も見つかりませんでした, Androidエミュレーターが主に使用され、isoは一度も使用されていないため. シミュレーターまたは実機でテストを実行できるかどうか, 開発が終わりに近づくまで, iOSシミュレーターでテストすると問題が見つかります.ビデオストリームの場合H264だと普通に再生できますが、ビデオストリームがH265だと回転しっぱなしですシミュレータと実機は再生できません(Androidエミュレータと実機の両方が再生できます)。後で、再生を調整するためにサードパーティのプラグインに変更する予定でした。
- 参照されている fijkplayer プラグインを pubspec.yaml にインポートします
# 视频解码器 软解码 fijkplayer: ^0.10.1
- 詳細なステータス
州名 プレーヤーのパフォーマンス アイドル アイドル状態、構築が完了したばかりの FijkPlayer がこの状態にあります。
この状態では、プレーヤーは少量のメモリを占有し、追加のスレッドは開始されません。
アイドル状態は、setDataSource を介してのみ初期化状態に変換できます初期化された アイドル状態と比較して、初期化完了状態には、入力メディア データ ソースに関する情報のみが含まれます。また、追加のスレッドは開かれません。 async準備中 非同期の準備状態。この状態に到達するには、初期化された状態で prepareAsync を呼び出します。
これは定常状態ではありません。この状態は、特定のタスクが完了するのを待ってから、準備済み状態に自動的に移行します。
この状態での主な準備作業は、メディア ファイルの種類を検出し、メディア ファイルを開き、デコーダを開いて新しいデコード スレッドを作成し、新しいデータ読み取りスレッドを作成し、オーディオ出力デバイスを開き、新しいビデオ出力スレッドを作成することです。など準備 asyncPreparing は、指定されたタスクを完了すると、この状態に自動的に移行します。
この状態では、オーディオとビデオのデータの一部がバッファリングされ、デコードされており、いつでも再生できます。始めました メディア (ビデオ、オーディオ) が再生されています。 一時停止 メディア (ビデオ、オーディオ) の再生が一時停止しました。 完了 メディア(ビデオ、オーディオ)の再生が完了しました。再生を最初からやり直すことができます。 停止 プレーヤーのさまざまなスレッドが占有していたリソースが解放されました。オーディオ デバイスがオフになっています。 終わり 手動で解放する必要があるプレーヤー内のすべてのメモリが解放されました。
この状態のプレーヤーは、ガベージ コレクションがメモリを解放するのを待つことしかできません。エラー プレーヤーでエラーが発生しました。 - 簡単な使用コードは次のとおりです。
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(); } }
- 使用後は正常にプレイできますが、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);
},
)
ここで行われます。単純な使用、カスタム使用、詳細を確認する必要がある場合は、公式ドキュメントを参照してください。アドレスは次のとおりです。