ハクソク

世界を動かす技術を、日本語で。

FFmpeg-over-IP – リモートFFmpegサーバーに接続する

概要

  • GPU搭載マシン上でffmpegをサーバー化し、クライアントからGPUトランスコードを利用可能
  • DockerやVM、リモートマシンでもGPUパススルーや共有ファイルシステム不要
  • クライアントはffmpeg互換のバイナリで、引数やI/Oをサーバーに転送
  • サーバー側でffmpegが実際にGPU処理を実行、ファイルはクライアントに留まる
  • NVENC/QSV/VAAPI/AMF/VideoToolboxなど幅広いHWアクセラレーション対応

GPUアクセラレートffmpegをどこからでも利用する方法

  • GPUトランスコードは高性能だが、アクセス構築が難題
    • Dockerでは**--runtime=nvidia**やデバイスマウント、ドライバーバージョンの調整が必要
    • VMではPCIeパススルーやSR-IOVなど複雑な構成、GPUがVMにロックされる問題
    • リモート利用時はNFS/SMB等の共有ファイルシステム、パスや権限管理の手間
  • インフラ構成を大幅変更せずにGPUトランスコードを利用したいニーズ

ffmpeg-over-ipによる解決策

  • GPU搭載マシンffmpeg-over-ipサーバーを起動
  • アプリケーションはffmpeg-over-ipクライアントをffmpegとして利用
  • クライアントはffmpegの引数をそのままサーバーへ転送
  • サーバーはパッチ済みffmpegで実処理、ファイルI/Oは全てクライアント経由でトンネリング
  • ファイルはサーバーに保存されずTCPポート1本のみで通信
  • GPUパススルー不要、NFS不要、SMB不要のシンプル構成

システム構成

  • クライアント(ファイル保有・GPUなし)
    • ffmpeg-over-ip-clientをffmpeg互換で実行
  • サーバー(GPU搭載)
    • ffmpeg-over-ip-serverがTCP:5050で待機
    • パッチ済みffmpegがI/Oをクライアントにトンネリング

主な特徴

  • リリースバイナリにffmpeg/ffprobe同梱、NVENC/QSV/VAAPI/AMF/VideoToolbox等幅広いHWアクセラ対応
  • ffmpegの別途インストール不要、両側でセットアップ簡単
  • 同時に複数クライアント接続可能、各セッションごとに独立したffmpegプロセス起動
  • **Linux(x86_64/arm64)、macOS(x86_64/arm64)、Windows(x86_64)**に対応

導入・運用情報

  • クイックスタート:docs/quick-start.md参照、数分で導入可能
  • バージョンアップガイド:docs/upgrading.md参照
  • 詳細設定:docs/configuration.md参照、設定ファイル探索パスや各種オプション
  • Docker統合:docs/docker.md参照、UNIXソケット利用やデバッグも解説
  • トラブルシューティング:docs/troubleshooting.md参照、よくある問題やデバッグ方法
  • ビルドガイド:CONTRIBUTING.md参照、ソースからのビルドやテスト方法

セキュリティ・ライセンス

  • 認証:HMAC-SHA256による共有シークレット署名、全コマンドをサイン
  • 通信:サーバーのみがポートを待ち受け、クライアントはアウトバウンド接続のみ
  • ライセンス:fioレイヤーとffmpegパッチ(fio/, patches/)はGPL v3、他はMITライセンス(詳細はLICENSE.md参照)

まとめ

  • GPU搭載マシンをサーバー化し、どこからでもffmpegのGPUトランスコードを利用可能
  • Docker/VM/リモート環境でのGPU利用の障壁を解消
  • シンプルなTCP接続のみで、安全かつ柔軟に運用可能

Hackerたちの意見

こんにちは、HN!個人プロジェクトのアップデートを紹介できることにワクワクしています。これは「ffmpeg-over-ip」と呼ばれていて、リモートのffmpegサーバーに接続できるんです。もし、GPUを搭載したマシン(WindowsのゲーミングノートPCやゲーミングPC、MacBookなど)と、GPUのないマシン(またはVM、Dockerコンテナなど)があれば、リモートのGPUを使ってGPUアクセラレーションによる動画変換ができちゃいます。仕組みは結構面白くて、サーバーとクライアントの2つのコンポーネントがあります。 - サーバー(GPUを持っている)はパッチを当てたffmpegを搭載していて、指定されたポートで待機しています。 - クライアント(GPUなし)はサーバーに接続して、サーバーからのファイルIOリクエストを受け取り、それをローカルで実行します。ffmpegはローカルファイルシステムを扱っているとは知らないので、このアプローチはHLSのような複数の入力や出力に対応できて、PlexやJellyfin、Embyのようなホームメディアサーバーにぴったりです。1つのサーバーが必要なだけクライアントにGPUを提供できて、全てのクライアントは自分のファイルシステムをリクエストに提供します。また、サーバーには静的ビルドのffmpegがバンドルされているので(jellyfin-ffmpegスクリプトからビルド)、設定ファイルを作成してパスワードを設定するだけで使えるようになります!これが最後に投稿されてから約1年半経ちました(https://news.ycombinator.com/item?id=41743780)。その時のフィードバックは、マシン間でファイルシステムを共有するのが難しいというものでしたが、それはもう問題ではないはずです。私のローカルセットアップでは本当に役立っています。皆さんにも役立つといいなと思っています。もし質問があれば、ウェブサイトにFAQがあります(GitHubリポジトリにリンクあり)、ここに投稿してもらえればお答えしますよ!ありがとう!
いいアイデアですね。IOについて詳しく教えてもらえますか?ffmpegサーバーがクライアントからブロックを読み取る方法はどうなってるんでしょう?それが大きな障害になりそうです。
ffmpeg.orgにパッチを提出してみたらどう?
ここにいるのを見れて嬉しい!Pundleでの君の仕事には本当に感心したよ。(あれは驚くほど速いHMR開発環境だったね - 今のViteみたいに。)自分だけが使ってる気がしてたけど、瞬時の更新から離れるのは難しかった。
これの意味は何なの?9500TやRyzen V1500Bの単一CPUコアで、60mbpsの4K H264を1080p 5mbpsのh264にリアルタイムで再エンコードできるよ。つまり、Jellyfinのためにモバイルでトランスコーディングするというコアユースケースには、PCでハードウェアビデオエンジンは9年間も必要なかったんだ。なんでみんなハードウェアビデオエンコーディングにこだわるのか全くわからない。完全に間違ってる。品質も悪いし、効率は赤いニシンだよ。ffmpegのIOスレッドには、設定を変えない限り、すべてのCPUコアを使うことになるし、設定を変えないよね。それに、Plexみたいなものでは面倒なセットアップやプレミアム機能が必要になる。全く意味がない!もしレイテンシが重要なら、ハードウェアエンジンは意味があるけど、ネットワーク経由で送ることでレイテンシを捨ててる。基本的に唯一のユースケースはゲームストリーミングで、その場合はローカルGPUがある。これらのffmpegネットワークハードウェアエンコードの革新が、実際のベンチマーク比較を持っているのを見たことがない。君は良かれと思って言ってるんだろうけど、本当に意味がないよ。
これ、かなり面白いね。ローカルマシン(とリモート)に接続して、任意のエンコードジョブを実行するために、ffmpegのフロントエンドで似たような実験をしてたんだ。そうすることで、エンコードタスクを別のマシンにオフロードしつつ、ローカルでキューイングメカニズムを保ってた。プロジェクトは https://ffmpeg-commander.com で、ffmpegコマンドを生成するためのものだけど、タスクをオフロードするための実験的なバックエンドもある。複数のサーバーでチャンクエンコーディングをサポートしてる? 大きな動画ファイルをサポートするための素晴らしい機能になると思う。
ffmpegは素晴らしいHTTPの入力と出力サポートがあるよ。最近、結構使ってる。node.jsでffmpegをラッピングして、内蔵のHTTPサーバーとクライアントを使ってやり取りしてる。ほとんどの場合、ディスクに触れる必要がないから、負荷もかなり減ったよ。
一部の処理(最新の圧縮技術を使ってすでに圧縮された動画をさらにダウンサイジングすること)はCPUやGPUに依存するけど、他の処理、例えば何千もの高解像度JPEGを軽く圧縮したタイムラプスにまとめるのは、IOに依存することが多いよね。このツールはどうやってそのトレードオフを実現してるんだろう?ローカルで処理した方がいいものもあれば、外部GPUにオフロードした方がいいものもあると思う。あと、帯域幅がメガビットかギガビットかでも大きな違いが出るよね。
これ、rffmpegとはパフォーマンスがどう違うんですか?https://github.com/joshuaboniface/rffmpeg
約1年半前に答えたことがあって、その答えは今でもほぼ正しいです: https://news.ycombinator.com/item?id=41743932 オペレーティングシステムを混ぜて使えるし、macOS、Windows、Linux、sudo権限は必要ありません。rffmpegは共有ファイルシステムが必要で、それを設定するのは大変かもしれません: https://github.com/joshuaboniface/rffmpeg/blob/master/docs/S... ffmpeg-over-ipはffmpegにパッチを当てて、サーバー用に1つのポートを開けるだけで、バイナリを実行すればOK。マウントは全く必要ありません。
これは基本的にPlan9がそのまま提供している機能を再現するソフトウェアですね。ほんと、Plan9がもっと普及してほしかった。完璧ではないけど、自分が望む方法でアプリケーションを実行するのに、ずっとずっと良い仕事をしてくれます。もし知らない人がいたら、Plan9のリモートアクセスの一つの方法は、必要なハードウェアを持つリモートマシンに「cpu」することです。ローカルのファイルシステムも一緒に持って行けて、リモートマシンの環境はローカルのファイルシステムがマウントされた状態になりますが、それはあなただけのものです。そこで実行するアプリケーションはリモートマシンのCPUで動作し、リモートマシンのハードウェアにアクセスできますが、ローカルのファイルシステムにはアクセスできるんです。SSHでリモートマシンに入って、全ての環境が一緒に持って行ける感じ、開発ツールも全部。これがPlan9のやってくれることです。だから、ffmpegがないけどGPUがあるマシンに「cpu」してffmpegを実行すると、ちゃんと動くし、簡単なコマンドラインフラグでハードウェアエンコーダーを使うように指示できるんです。
Plan 9の素晴らしいところは、他の分散システムをすごく複雑に見せるところだね。Plan 9の最悪なところも、他の分散システムをすごく複雑に見せるところだ!
これはいいプロジェクトのようだけど、最近の「Show HN」に対する偏見のせいで、タイトルにそれを入れずにShow HNしてるのかな?
これは人間のエラーだと思ってもらうしかないですね。投稿する興奮のあまり、Show HNを省いちゃいました。
Show HN?それって何? :-) ハッカーニュースはずっと読んでるけど、ハッカーニュースで技術を見せることに関する何かの慣習を見逃してたみたい。
ああ、今見えた。メニューオプションなんだね。全然気づかなかったよ :-)
表面的にはこれはひどいアイデアに思えるね。FFmpegは非常に複雑なCコードの山で、信頼できない入力を処理するのが仕事なんだ。信頼できない入力があるのに、そんなコードをネットワーク対応にするのは、できればサンドボックス化することをおすすめするよ。そうしないと、トラブルを招くことになる。
コメントありがとう!こういうのは、サーバーとクライアントの両方をコントロールできるときに使うケースだね。各リクエストには基本的なHMAC認証が組み込まれてるよ。> できればサンドボックス化することをおすすめする。サーバーは特別な権限が必要ない標準的なバイナリだから、アクセスできるファイルやGPUの制限されたセットだけにアクセスできる、最も厳重にロックされたユーザーを作れば、うまくいくよ。これが推奨されてる。
ずっとこれを作ろうと思ってたんだけど、他の誰かがやってくれたおかげで待った甲斐があったよ!ffmpegをパッチする代わりに、サーバー側でFUSEを使うことを考えたことある?逆sshfsみたいな感じで?これならffmpegバイナリをパッチする必要がなくて、他の人のパッチが施された奇妙で素晴らしいffmpegバイナリを使えるんだ。SBC GPUでどれくらいうまく動くか見てみたいな。多くのものはハードウェアデコードとエンコードを持ってて、ベンダーはffmpegをフォークするのが好きだから。
ffmpegがsftpをサポートしてるから、sftpを探ってみたんだけど(-i sftp://...)、コードがかなりバグってて、これを変更できるようにパッチを上流に提出したいと思ってる。対照的にFTPは、少なくともコードを見た感じではかなり安定してた。FTPには他にも使いづらい欠点があったから、私のユースケースには向いてなかった。それが一つの動機で、もう一つはサーバーに入る引数を書き直す必要があるから。君が説明してるのは、基本的にffmpeg-over-ip v4(その前のバージョンも!)のことだったし、常に聞いてたフィードバックはファイルシステムを共有するのは手間がかかりすぎるってこと。WindowsやmacOSのsshサーバーは使いづらいし、みんなバンドルされたソリューションを使いたがってる。ffmpegをフォークするのは簡単じゃなかった!ビルドプロセスを理解するのに時間がかかって、最終的にはjellyfinのビルドスクリプトを使うことにしたけど、上流のHEADから数バージョン遅れてるのが難点だね。
これをFoIPと呼ぶチャンスを逃したね。
これがポートフォワーディングってやつ?(疲れすぎてて、これを読む集中力がないから寝るね。)
要約すると: - クライアントがサーバーにリクエストを送る(それが双方向のネットワークソケットを開く) - サーバーはその双方向ソケットを使って、vfsのような特性を持つローカルのパッチを当てたffmpegを起動する - ffmpeg(クライアント-サーバーの双方向ソケットを使って)は、クライアントのファイルシステムをローカルのように扱いながら入出力操作を行う だから、クライアントはポートを開いたり、従来のマウント方式でファイルシステムを公開する必要がなくて、1つのサーバーが複数のクライアントのファイルシステムやリクエストを処理できるんだ。
ffmpegにはすでにネットワーク機能があるよね。TCPソケットを開いて、そこから入力をストリーミングしたり、別のTCPソケットに出力を書き込むことができる。これと何が違うの? これは便利さのためのラッパーに過ぎないのか、それとも根本的に新しい機能を提供しているの?
メディアサーバーのユースケースで、ffmpegのネイティブなネットワーク機能を使って、入力をストリーミングして、そこから複数の出力(HLSを考えてみて)をストリーミングバックするのは、現時点では不可能なんだ。HTTP、FTP、SFTPにはそれぞれ制限があって、HLSのユースケースには明らかに壊れているものもあるし、他はシークストリーミングができない。vfsレイヤーを追加するためにffmpegをパッチ当てたり、コーデックやhwaccelを追加した後のビルドパイプラインを理解するのにたくさんの時間を費やす代わりに、内蔵機能を使いたかったな。将来的にはこれを変えられることを願ってる。いくつかのバグを特定したから、パッチを提出するつもりだよ。
これって一般化できるかな?リモートクライアントのファイルシステムに対するI/Oシステムコールをインターセプトするラッパー?これならffmpeg以外のバイナリでも動くと思うんだけど。
そうだね、どんなバイナリにもパッチを適用してビルドして、ffmpegって名前にすれば、サーバーとクライアントを含めてネットワーク越しに動くよ。