UDPストリーミングとは

UDP(User Datagram Protocol)は、データを送る方式(トランスポートプロトコル)のひとつです。TCPと違い、送る前に相手と接続を確立しません(コネクションレス)。接続の手続きも再送もしないぶん処理が軽く、少ない遅延で映像を送れます。FFmpegは udp:// で、このUDPに直接対応しています。

ただしUDPには、途中で失われたパケット(パケットロス)を取り戻す仕組みがありません。SRTや、TCPを使うRTMPと違い、消えたパケットは送り直されません。ネットワークでパケットが落ちれば、そのぶん映像が乱れます。

向いている用途と向いていない用途は、次のとおりです。

向いている用途 向いていない用途
管理されたLAN内の伝送 インターネット越しの配信
スイッチ直結など低ロス環境 無線・モバイルなどロスが多い経路
超低遅延が必要な現場(中継・モニタリング) ロス耐性・信頼性が必須の配信

UDPで送るときの入れ物(コンテナ)には、配信に向いたMPEG-TS(MPEG Transport Stream)を使います。FFmpegでは -f mpegts で指定します。MPEG-TSは188バイト固定長のパケットでできていて、途中から受信を始めても読み取れます(自己同期)。そのため、ライブの伝送に向いています。

ユニキャスト送受信

ユニキャストは、1つの送信元から1つの受信先へ送る、1対1の伝送です。送り先として、受信側のIPアドレスとポート番号を指定します。

送信(再エンコードなし)

入力がすでに配信に向いたコーデック(H.264 + AAC)なら、再エンコードせずにそのまま流すのがいちばん軽い方法です。

ffmpeg -re -i input.mp4 -c copy -f mpegts "udp://192.168.1.50:1234"
  • -re:ファイルを本来の速さ(フレームレートどおり)で読み込みます。付けないとFFmpegはできるだけ速くファイルを送ってしまい、ライブの伝送になりません。リアルタイム配信では必須です。
  • -c copy:再エンコードせず、そのままコピーします。CPUの負荷が低く、画質も落ちません。
  • -f mpegts:コンテナをMPEG-TSにします。
  • udp://192.168.1.50:1234:送り先(受信する側)のIPアドレスとポート番号です。

受信して保存

受信側では 0.0.0.0 を指定して待ち受け、届いた映像をファイルに保存できます。

ffmpeg -i "udp://0.0.0.0:1234" -c copy received.mp4

0.0.0.0 は、このマシンのすべてのネットワークインターフェースで、指定したポートを受信するという意味です。-c copy なので、再エンコードせずにそのまま received.mp4 に書き出します。

受信して再生(ffplay)

保存せずに映像を見るだけなら、ffplay で再生できます。

ffplay "udp://0.0.0.0:1234"

送信側と受信側を別々のマシンで(または同じマシンの別のターミナルで)起動すると、LANでの低遅延の伝送をすぐに試せます。

マルチキャスト配信

マルチキャストを使うと、1回の送信で複数の受信者に同時に届けられます。送信側はネットワークに1本のストリームを流すだけです。対応したスイッチやルーターが、受け取りたい受信者の分だけ複製して届けます。受信者が増えても、送信側の帯域は増えません。

マルチキャストには、専用のIPアドレスの範囲を使います。よく使うのは 239.0.0.0/8(管理スコープ。組織の中で使うために予約された範囲)です。インターネット上のアドレスとぶつからないので、LAN内の配信に安心して使えます。

マルチキャスト送信

ffmpeg -re -i input.mp4 -c copy -f mpegts "udp://239.0.0.1:1234?pkt_size=1316"

ユニキャストとの違いは、宛先がマルチキャストアドレス(239.0.0.1)になっている点です。pkt_size=1316 は、1回に送るパケットの大きさです。ポート番号(1234)は、用途に合わせて変えてかまいません。

マルチキャスト受信

受信側は、送信側と同じマルチキャストアドレスを指定します。

ffplay "udp://239.0.0.1:1234"

同じアドレスを指定した受信者は、複数台あっても全員が同じストリームを受け取れます。デジタルサイネージや教室での一斉配信のように、同じ映像をたくさんの端末に届けたいときに便利です。

マルチキャストが届くかどうかは、ルーターやスイッチの設定(IGMPへの対応など)で決まります。家庭用ルーターや一部のスイッチは、マルチキャストを通さないことがあります。届かないときは、ネットワーク機器の設定を確認してください。

主要パラメータ(pkt_size・fifo_size・overrun_nonfatal)

UDPの設定は、URLの後ろに ?key=value&... の形で付けます。

pkt_size

pkt_size は、UDPで1回に送るパケットのバイト数です。MPEG-TSのパケットは188バイト固定なので、その整数倍にするのが基本です。

188 バイト × 7 = 1316 バイト

pkt_size=1316 は、MPEG-TSのパケットちょうど7個分です。一般的なイーサネットのMTU(1回に送れるパケットの最大サイズ。1500バイト)にも収まるので、パケットが途中で分割される(IPフラグメンテーション)のを避けられます。UDPでMPEG-TSを流すときの推奨値です。

ffmpeg -re -i input.mp4 -c copy -f mpegts "udp://192.168.1.50:1234?pkt_size=1316"

fifo_size と overrun_nonfatal

受信側は、届いたパケットをいったん内部のバッファ(FIFOバッファ。リングバッファとも呼びます)にためてから処理します。送る速さが速いときや、受信側の処理が一時的に追いつかないときは、このバッファがあふれることがあります。

  • fifo_size:受信バッファの大きさです。大きくすると、一時的にどっと届いたデータを受け止められます。単位はパケットの数で、既定値より大きくすると途切れにくくなります。
  • overrun_nonfatal=1:バッファがあふれても(オーバーラン)、エラーで止まらずに受信を続けます。多少データが欠けても、受信を止めたくないときに使います。

両方を使った受信コマンドです。

ffmpeg -i "udp://0.0.0.0:1234?overrun_nonfatal=1&fifo_size=1000000" -c copy received.mp4

fifo_size=1000000 で大きめのバッファを用意し、overrun_nonfatal=1 であふれても止まらないようにしています。「Circular buffer overrun」と出て受信が止まるときは、この2つで安定させます。

再エンコードして送出する

入力のビットレートが大きすぎる、コーデックが対応していない、といった場合は、送るときに再エンコードします。次の例は、遅延を抑え、映像のビットレートを 2Mbps 前後に抑える設定です。

ffmpeg -re -i input.mp4 -c:v libx264 -preset veryfast -b:v 2000k -maxrate 2000k -bufsize 4000k -pix_fmt yuv420p -g 60 -c:a aac -b:a 128k -f mpegts "udp://192.168.1.50:1234?pkt_size=1316"

各オプションの意味:

オプション 意味
-c:v libx264 映像をH.264にエンコード
-preset veryfast エンコード速度優先(ライブで遅延を抑える)
-b:v 2000k 映像ビットレート目標 2Mbps
-maxrate 2000k / -bufsize 4000k 2Mbpsを長く超えないようにする。キーフレームなどで一瞬超えることはあり、単純な映像では下がる
-pix_fmt yuv420p 互換性の高いピクセルフォーマット
-g 60 キーフレームの間隔を最大60フレームにする(受信開始点を増やす)
-c:a aac -b:a 128k 音声をAAC 128kbpsにエンコード
-f mpegts MPEG-TSコンテナで送出

-maxrate と -bufsize を付けると、映像のビットレートが2Mbpsを長く超えることはなくなります。ただし、パケットの送り方までは平らになりません。FFmpegはフレームができるとすぐに送るので、キーフレームは2Mbpsを大きく超える勢いで一度に送られます。音声やMPEG-TSのデータも上乗せされるので、ネットワークの帯域には余裕を残してください。-g 60 でキーフレームを定期的に入れておくと、受信側が途中からつないでも、すぐに映像が出ます。

RTMP・SRTとの使い分け

ライブ伝送のプロトコルは、用途に合わせて選びます。

プロトコル トランスポート ロス回復 主な用途
UDP UDP 無し LAN内の超低遅延伝送・モニタリング
SRT UDP + 再送 有り(ARQ) 不安定な回線・インターネット越しの低遅延配信
RTMP TCP 有り(TCP) 配信プラットフォームへの入稿(YouTube/Twitch等)

選び方の目安:

  • UDP:自分たちで管理している閉じたLANで、とにかく遅延を小さくしたいとき。スイッチに直結するような、パケットがほとんど落ちない環境が前提です。インターネット越しや、ロスの多い経路には向きません。
  • SRT:インターネット越しでも、遅延を小さく保ちたいとき。UDPをもとにしていますが、独自の再送(ARQ)で失われたパケットを取り戻せます。
  • RTMP:配信サービスに映像を送るとき。多くのサービスが受け付けていて、TCPを使うので確実に届きます。

よくあるエラーと対処

受信できない

次の順に確認します。

  • ポート番号:送信側と受信側で同じポート(例:1234)を指定しているか。
  • ファイアウォール:受信側のファイアウォールが、そのUDPポートを止めていないか。Windowsや、Linux(ufw/firewalld)で受信ポートを開けます。
  • マルチキャスト:ルーターやスイッチがマルチキャスト(IGMP)を転送しない設定だと届きません。同じスイッチにつないだ機器どうしで試す、ネットワーク機器のマルチキャスト設定を確認する、といった方法で原因を絞り込みます。

映像が乱れる

ブロックノイズや音飛びが出るなら、パケットが落ちている可能性が高いです。UDPは落ちたパケットを取り戻せないので、ネットワークの側で対処します。

  • 帯域に余裕を持たせる(-maxrate を下げてビットレートを抑える、有線でつなぐ)。
  • 経路の混雑(輻輳)を解消する。
  • どうしてもパケットが落ちる経路なら、失われたパケットを取り戻せるSRTへの切り替えを考えます。

Circular buffer overrun

受信側のバッファがあふれたことを示すエラーです。受信の処理が、届くデータの量に追いつかないときに出て、overrun_nonfatal=1 を付けていなければ、そこで受信が止まります。

ffmpeg -i "udp://0.0.0.0:1234?overrun_nonfatal=1&fifo_size=1000000" -c copy received.mp4

fifo_size を大きくしてバッファを増やし、overrun_nonfatal=1 であふれても止まらないようにします。

遅延が大きい

fifo_size は受け止められる量の上限なので、大きくしただけでは遅延は増えません。遅延が増えるのは、受信側の処理が追いつかず、バッファにデータがたまったときです。遅延をいちばん小さくしたいなら、再エンコードの -preset を速いものにし、受信側の処理が遅れないようにします。

関連記事

よくある質問

UDPとSRTはどちらを使うべき?

管理されたLANで、パケットがほとんど落ちないなら、軽くて遅延がとても小さいUDPを選びます。インターネット越しや無線のように、パケットが落ちる経路では、落ちたパケットを取り戻せる(ARQ)SRTが向いています。

pkt_size はなぜ 1316 なのか?

MPEG-TSのパケットは188バイト固定で、イーサネットのMTU(1500バイト)に収まるのは7個分(188×7=1316)までだからです。FFmpegの既定の1472バイトもMTUには収まりますが、188の倍数ではないので、TSのパケットが2つのUDPパケットにまたがります。UDPでMPEG-TSを流すときの定番の値です。

マルチキャストアドレスはどの範囲を使えばいい?

LAN内で使うなら 239.0.0.0/8(管理スコープ)が安全です。組織の中で使うために予約されていて、インターネット上のアドレスとぶつかりません。受信側が送信側と同じアドレスとポートを指定すれば、複数台で同時に同じストリームを受け取れます。

-re を付け忘れるとどうなる?

FFmpegがファイルをできるだけ速く送ってしまい、受信側がリアルタイムで処理しきれなくなります。ファイルをライブのように流すときは、本来の速さで読み込む -re が必須です。