1. 導入:なぜGoとFFmpegなのか?
Go言語(Golang)は、その高い並行処理能力とシンプルな構文から広く採用されています。そのため、動画処理やストリーミングサービスなど、処理速度が求められるバックエンドシステムに最適です。
そして、動画処理のデファクトスタンダードである FFmpegをGoから呼び出します。これにより、堅牢かつ高速な動画連結システムを構築できます。
この記事では、Goの os/exec パッケージを用いてFFmpegコマンドを実行します。具体的な手順として、複数の動画ファイルを結合する具体的な手順を解説します。
2. FFmpegによる動画連結の原理
FFmpegで複数の動画(例:input1.mp4, input2.mp4)を結合する最も確実な方法は、**デムクサー(Demuxer)を利用した連結ファイル(Concat List)**方式です。
2.1 連結ファイル(Concat List)の作成
FFmpegに直接動画ファイルを渡すのではありません。代わりに、結合したい動画のパスをリスト化したテキストファイル(例: mylist.txt)を事前に作成します。
注意: 動画のエンコード方式や解像度が異なる場合、連結前にエンコードを統一する必要があります。さもないと、エラーが発生したり、予期せぬ結果になることがあります。
mylist.txt の内容例:
Plaintext
file 'input1.mp4'
file 'input2.mp4'
file 'input3.mp4'
2.2 Go言語での連結ファイル作成
Go言語のコードで、動的にこのテキストファイルを生成します。
Go
package main
import (
"os"
"path/filepath"
)
// 結合したい動画ファイル名のリスト
var inputFiles = []string{"input1.mp4", "input2.mp4", "input3.mp4"}
const concatListFile = "mylist.txt"
func createConcatList() error {
// ファイルを作成します
f, err := os.Create(concatListFile)
if err != nil {
return err
}
defer f.Close()
// ファイルリストを書き込みます
for _, file := range inputFiles {
line := "file '" + filepath.Base(file) + "'\n"
if _, err := f.WriteString(line); err != nil {
return err
}
}
return nil
}
3. GoからFFmpegを実行し動画を結合する
連結ファイル (mylist.txt) が用意できたら、次に Goの os/exec パッケージを使用してFFmpegコマンドを実行します。
3.1 FFmpegコマンドの構造
動画を再エンコードせずに高速に結合する場合、以下のコマンド形式を使用します。
Bash
ffmpeg -f concat -i mylist.txt -c copy output.mp4
| オプション | 意味 |
-f concat | 入力形式として連結デムクサーを使用することを指定します。 |
-i mylist.txt | 連結リストファイルをインプットとして指定します。 |
-c copy | コーデックをコピーします(つまり、再エンコードしないため高速です)。 |
output.mp4 | 出力ファイル名です。 |
3.2 Go言語での実行コード
os/exec を使用してFFmpegコマンドを実行し、エラー処理を行います。
Go
package main
import (
"log"
"os/exec"
)
func runFFmpegConcat() error {
// 実行するFFmpegコマンドと引数を定義します
cmd := exec.Command("ffmpeg",
"-f", "concat",
"-i", concatListFile, // 作成した連結リストファイル
"-c", "copy",
"output_final.mp4",
)
log.Printf("FFmpegコマンドを実行中: %s\n", cmd.String())
// 標準出力と標準エラー出力を取得(デバッグ用)
output, err := cmd.CombinedOutput()
if err != nil {
log.Printf("FFmpeg実行エラー: %s\n", string(output))
return err
}
log.Println("動画の連結が完了しました: output_final.mp4")
return nil
}
func main() {
if err := createConcatList(); err != nil {
log.Fatalf("連結リスト作成エラー: %v", err)
}
// リスト作成に成功したら、FFmpegを実行します
if err := runFFmpegConcat(); err != nil {
log.Fatalf("FFmpeg実行に失敗しました: %v", err)
}
}
4. まとめと発展的な応用
Go言語とFFmpegの組み合わせは、動画処理バックエンドを構築する上で強力な選択肢です。
応用例:
- 再エンコードを伴う連結: 入力動画の解像度やビットレートを統一したい場合は、
-c copyの代わりに-c:v libx264 -preset fastなどのエンコード設定を指定します。 - エラー処理の強化: 大規模なシステムでは、Goルーチンを利用してFFmpegの実行ログをパースし、進捗を監視する機能を実装することで、さらに堅牢な動画処理パイプラインを構築できます。
この方法を応用すれば、Go言語でユーザーがアップロードした動画の処理を効率的に行うことが可能です。

コメント