ffmpegを介してビデオストリーミングを実現するために、Linuxマシンでffserverプロセスを実行しています。ただし、ビデオストリーミングには遅延があります。 ffserver構成ファイルPort 8090
を定義します。
コマンドnetstat -tulnapは私にこれを与えます:
root@beagleboard:/etc# netstat -tulnap
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address Stat e PID/Program name
tcp 0 0 0.0.0.0:68 0.0.0.0:* LIST EN 654/pump
tcp 0 0 0.0.0.0:111 0.0.0.0:* LIST EN 662/portmap
tcp 0 0 0.0.0.0:22 0.0.0.0:* LIST EN 698/dropbear
tcp 0 0 0.0.0.0:8090 0.0.0.0:* LIST EN 744/ffserver
tcp 0 52 192.168.1.104:22 192.168.1.111:10838 ESTA BLISHED 724/dropbear
udp 0 0 0.0.0.0:514 0.0.0.0:* 703/syslog-ng
udp 0 0 0.0.0.0:111 0.0.0.0:* 662/portmap
udp 0 0 0.0.0.0:60628 0.0.0.0:* 709/avahi-daemon: r
udp 0 0 0.0.0.0:5353 0.0.0.0:* 709/avahi-daemon: r
ご覧のとおり、ffserverプロセスはtcpプロトコルを使用して送信しますが、これがビデオストリーミングの遅延の原因であると思われます。プロセスにプロトコルまたはUDPプロトコルを使用させるにはどうすればよいですか?ポートを変更する必要がありますか?
プログラム自体の一部を書き直さずに、TCPではなくUDPを使用するようにプログラムに強制することはできません。これらのプロトコルは、互換性を保つにはあまりにも異なっています。
TCPはストリーム指向です(受信者は、送信者が出力した正確な順序ですべてを連続ストリームと見なします)。 UDPはデータグラム指向です(各データグラムは個別のパケットで送信され、並べ替えることもできます)。
TCPにはフロー制御があるため、送信者(または送信者のOS)は、リンクをオーバーフローしたり、他の接続に大きな影響を与えたりすることなく、データを送信する速度を正確に把握しています。 UDPはこれを行いません。「強制」が不十分なプログラムは、リンク速度に関係なく、UDPを介して1秒あたりギガバイトのデータの送信を開始する可能性があります。
TCPには再送信があるため、パケットが途中でドロップされた場合(たとえば、ネットワークが過負荷であるか、その他の問題があるため)、パケットは再送されます。プロトコルが信頼できるトランスポートに依存していて、UDPを経由するように強制すると、少なくとも1つのパケットが失われるとすぐに接続が完全に停止する可能性があります。 (そしてパケットwill失われます;上記のポイント#1と#2を参照してください。)
他の人が言及したように、UDPとTCPは根本的に異なるプロトコルです。
ただし、TCPではなくUDPを介してデータをmust転送する必要がある場合は、 socat などのリレーツールを使用できます。 TCP接続をリッスンし、TCPストリームの内容をUDPストリームとして別のホストに転送するようにsocatを構成できます。他のホストがTCPトラフィックが予想される場合、そこでリレーの別のインスタンスを使用してTCPに戻すことができます。これにより、ホスト間リンクから再試行と確認応答が削除されます。再試行と確認応答は引き続き実行されます。ローカルリレーツールとローカルアプリケーションの間に存在しますが、ローカルループバックリンクで再試行が発生する可能性はほとんどありません。
ただし、これで遅延の問題が解決する可能性はほとんどありません。アプリケーションがUDPの代わりにTCP)を使用するように構築されている場合、パケットのドロップを許容できない可能性があります。その場合、このハッキングによって不安定な動作が発生する可能性があります。
非常に遅い接続を使用している場合を除き、遅延の問題はビデオコーデックが原因である可能性があります。
ビデオを効率的に圧縮するには、予測エンコーディングを使用する必要があります( ウィキペディアのこの記事 を参照)。
予測コーディングは基本的に、前または後の画像から画像を計算します。これには、次の意味があります。
多くのPフレーム(以前のフレームから計算)を使用する場合、クライアントが持っているため、ビデオの表示が開始する前に遅延が発生します次の完全なビデオフレーム(Iフレーム)を待ちます。ただし、ストリームが確立されると、ビデオを比較的遅れることなく視聴できます。
Bフレーム(前の画像と後の画像から計算)を使用する場合、非常に大きな遅延が発生します。上からの最初の遅延に加えて、クライアントは次のIフレームが最後のIから再生を開始するのを待つ必要があります。 -フレーム。これにより、ラグが発生します(クライアントは、サーバーがビデオを記録/送信するよりも著しく遅く、多くの場合数秒でビデオを再生します)。ビデオをオンザフライでエンコードしている場合は、サーバーからの遅延も発生します。次のIフレームが前のIフレームから始まるすべてを送信するのを待つ必要があります。
ほとんどのコーデックでは、必要に応じてBフレームとPフレームの使用法を微調整できますが、圧縮効率とのトレードオフの遅延があります。
十分な帯域幅がある場合は、 [〜#〜] mjpeg [〜#〜] のように、B-/Pフレームなしでコーデックを使用することもできます。
遅延のもう1つの理由は、プレーヤー側でのバッファリングであるため、ネットワークの伝送が不安定な場合でも歪みは発生しません。多くのビデオプレーヤーでは、バッファサイズを微調整できます。