FFmpegで変換したら「映像はあるのに音が出ない」「複数あったはずの音声トラックが1本に減っている」という事故は非常によく起きます。原因は大きく4つに絞れます。本記事では、まず ffprobe で状況を確認し、原因を1つずつ切り分けて確実に直す手順を解説します。
動作確認: ffmpeg 6.1 で確認済み
この記事でわかること
- 出力から音声が消える「典型的な4つの原因」と、それぞれの直し方
ffprobeを使って「入力に音声があるか・何トラックあるか」を最初に確認する方法-mapのマップ漏れ、-anの混入、コンテナ非対応コーデック、複数トラックの既定挙動という4パターンの切り分け0:v:00:a:1といったストリーム指定子の読み方
音が消える問題は「入力に音声があるか」「FFmpegに音声を出力するよう指示しているか」「コンテナが音声コーデックを受け入れられるか」の3点をこの順で確認すれば、ほぼ確実に原因にたどり着けます。
まず ffprobe で確認する
音が出ないとき、最初にやるべきは「そもそも入力に音声トラックが存在するのか」の確認です。入力に音声が無ければ、FFmpegのコマンドをいくら直しても音は出ません。次のコマンドで音声ストリームだけを一覧表示します。
ffprobe -v error -select_streams a -show_entries stream=index,codec_name,channels -of csv input.mp4
出力例:
stream,1,aac,2
この場合、インデックス 1 にコーデック aac・2 チャンネルの音声トラックが1本あることが分かります。複数あれば行が複数表示されます。
stream,1,aac,2
stream,2,ac3,6
逆に 何も表示されない(空行のみ) であれば、入力ファイルに音声トラックが存在しません。この場合は元素材の問題なので、別の入力を用意するか、無音トラックを別途追加する方向で考えます。
- 音声トラックがある → 次の「原因①〜④」で出力側の問題を切り分ける
- 音声トラックが無い → 入力素材そのものに音声が無い(FFmpegの問題ではない)
「入力に音声がある」と確認できたら、以降の原因を順に潰していきます。一番手早く確実なのは、全ストリームを保持して出力するやり方です。
ffmpeg -i input.mp4 -map 0 -c copy output.mkv
-map 0 で入力0番の全ストリーム(映像・音声・字幕すべて)を選択し、-c copy で再エンコードせずそのままコピーします。これで「FFmpegが音声を落としているのか、それとも入力に元から無いのか」を切り分けられます。これで音が残るなら、消えていたのは元のコマンドの書き方が原因です。
原因①: -map のマップ漏れ
-map を 一切書かない 場合、FFmpegは各種別から「ベストな」ストリームを自動選択します。多くの場合は映像1本+音声1本が選ばれ、音は残ります。
問題は -map を 一部だけ書いた ときです。-map を1つでも指定すると自動選択は無効になり、明示的にマップしたストリームしか出力されません。たとえば次のように映像だけマップすると、音声は完全に落ちます。
# NG: 映像しかマップしていない → 音声が消える
ffmpeg -i input.mp4 -map 0:v:0 -c copy output.mp4
解決策は、音声のマップを追加することです。映像と全音声を明示的に指定します。
ffmpeg -i input.mp4 -map 0:v -map 0:a -c copy output.mp4
-map 0:v— 入力0番の全映像ストリーム-map 0:a— 入力0番の全音声ストリーム
「-map を使い始めたら、必要なストリームは全部書く」が鉄則です。映像を選んだなら、音声・字幕も忘れず書き足してください。
原因②: -an で除去している
-an は「audio none」、つまり 音声を出力しない オプションです。これがコマンドのどこかに紛れていると、当然ながら音声は出力されません。
# NG: -an が入っているので音声が出ない
ffmpeg -i input.mp4 -an -c:v libx264 output.mp4
スクリプトをコピペで使い回しているとき、無音動画用に付けた -an がそのまま残っていた、というのが典型パターンです。解決は単純で、-an を削除するだけです。
ffmpeg -i input.mp4 -c:v libx264 -c:a aac output.mp4
同様に、映像を捨てる -vn(video none)もあります。音声だけ抽出したいときは -vn を使いますが、逆に「映像が消えた」場合は -vn の混入を疑ってください。コマンド全体を見直し、意図しない -an / -vn が無いかをチェックします。
原因③: コンテナ非対応コーデック
これが最も見落とされやすい原因です。-c copy(ストリームコピー)は速くて無劣化ですが、出力コンテナがその音声コーデックに対応していないと、FFmpegが音声を黙って落とす(または書き込みに失敗する) ことがあります。
代表例が MP4 × Opus / Vorbis です。WebMファイルの音声は多くがOpusですが、MP4はOpusを標準ではうまく扱えません。次のようにそのままコピーしようとすると、音声がうまく入らないことがあります。
# 問題が起きやすい: WebM(Opus/Vorbis) を MP4 にそのままコピー — 失敗または音声欠落
ffmpeg -i input.webm -c copy output.mp4
映像が MP4 対応(H.264/H.265/VP9)の場合、解決策は音声だけを コンテナが対応するコーデックに再エンコード することです。MP4ならAACが鉄板です。
ffmpeg -i input.webm -c:v copy -c:a aac output.mp4
-c:v copy— 映像はコピー(無劣化・高速)-c:a aac— 音声だけAACに再エンコードし、MP4で確実に再生できるようにする
-c:v copy が使えるのは映像コーデックがMP4対応(H.264・H.265・VP9)の場合だけです。古い VP8 の WebM は MP4 にコピーできないため、映像も再エンコードしてください: ffmpeg -i input.webm -c:v libx264 -crf 20 -c:a aac output.mp4。
コンテナごとの音声コーデック対応の目安は次の通りです。
| コンテナ | 対応しやすい音声コーデック | 備考 |
|---|---|---|
| MP4 | AAC / MP3 / AC3 | Opus は限定的。基本は AAC へ再エンコード |
| MKV | ほぼ何でも(AAC/Opus/Vorbis/FLAC/AC3…) | 困ったら MKV にすれば -c copy で通ることが多い |
| WebM | Opus / Vorbis | 映像は VP8/VP9/AV1 |
つまり「再エンコードしたくない=-c copy で通したい」なら、出力をMKVにするのが最も手堅い選択です。MKVなら大半の音声コーデックをそのままコピーできます。MP4にこだわる必要があるときだけ、音声をAACへ再エンコードしてください。
原因④: 複数音声トラックで先頭のみ
入力に音声トラックが複数あるとき(例: 日本語+英語の二か国語)、-map を書かない既定の自動選択では 音声は基本的に1本しか選ばれません。結果として「英語音声が消えた」「副音声が無くなった」という事故になります。
ffprobe で複数トラックを確認したうえで、目的に応じて次のように対応します。
全トラックを残したい場合 は -map 0 ですべてのストリームを保持します。
ffmpeg -i input.mp4 -map 0 -c copy output.mkv
特定のトラックだけを選びたい場合 は、ストリーム指定子で狙ったトラックをマップします。たとえば「映像の1本目+音声の2本目」を出したいなら次の通りです。
ffmpeg -i input.mkv -map 0:v:0 -map 0:a:1 -c copy output.mp4
-map 0:v:0— 入力0番の1番目の映像-map 0:a:1— 入力0番の2番目の音声(インデックスは0始まり)
複数音声を扱うときは「既定では1本しか残らない」という前提を覚えておき、必要なものを -map で明示するのがポイントです。複数トラックの扱いは 複数音声トラックの操作 も合わせて参照してください。
ストリーム指定子の読み方
-map で使う 0:a:1 のような表記は ストリーム指定子(stream specifier) と呼ばれ、慣れると音声トラブルの大半を自力で解決できます。読み方は次の通りです。
0 : a : 1
↑ ↑ ↑
入力 種別 その種別内のインデックス(0始まり)
番号
- 1つ目の数字 = 入力ファイルの番号(
-iの順で 0, 1, 2…) - 真ん中の文字 = ストリームの種別(
v=映像 /a=音声 /s=字幕) - 最後の数字 = その種別の中での何番目か(0始まり)
具体例で読み解くと:
| 指定子 | 意味 |
|---|---|
0:v:0 | 1番目の入力の、1番目の映像ストリーム |
0:a:1 | 1番目の入力の、2番目の音声ストリーム |
0:a | 1番目の入力の、すべての音声ストリーム |
1:a:0 | 2番目の入力の、1番目の音声ストリーム |
ここで注意したいのは、インデックスが0始まりだという点です。「2番目の音声」を指したいなら 0:a:1 であって 0:a:2 ではありません。ffprobe で表示される index はファイル全体での通し番号(映像・音声・字幕を含む)なので、-map で使う種別ごとの番号とは別物です。指定子の a:N は「音声の中で何番目か」を表す、と覚えておくと混乱しません。ストリーム選択全般は ストリームのマッピング でも詳しく解説しています。
よくある質問
ffprobe では音声があるのに、出力すると消えます
ほぼ確実に出力側の問題です。①-map を使っていて音声マップを書き忘れていないか、②-an が紛れていないか、③出力コンテナが音声コーデックに非対応(MP4にOpusなど)で -c copy が落としていないか、をこの順で確認してください。まず ffmpeg -i input.mp4 -map 0 -c copy output.mkv で全保持を試すと切り分けが早いです。
MP4にしたら音が出ません。MKVだと出ます
MP4が音声コーデックに対応していない典型例です。元の音声がOpusやVorbisだと、MP4へのコピーで落ちることがあります。音声だけAACに再エンコードしてください: ffmpeg -i input.webm -c:v copy -c:a aac output.mp4。再エンコードを避けたい場合は出力をMKVにすれば -c copy で通ることが多いです。
二か国語の動画なのに片方の音声しか残りません
入力に音声トラックが複数あると、-map 未指定の既定では音声が1本しか選ばれないためです。全部残すなら -map 0、特定のトラックだけなら -map 0:a:0 -map 0:a:1 のように欲しいトラックを明示してください。どのトラックが何番かは冒頭の ffprobe コマンドで確認できます。
「2番目の音声」は 0:a:2 ですか?
いいえ、0:a:1 です。ストリーム指定子のインデックスは0始まりなので、1番目が 0:a:0、2番目が 0:a:1 になります。ffprobe が表示する index(ファイル全体の通し番号)とは別なので混同しないよう注意してください。
関連記事
動作確認: ffmpeg 6.1 / Ubuntu 24.04 (検証スクリプトで実行確認)
一次ソース: ffmpeg.org/ffmpeg.html / trac.ffmpeg.org/wiki/Map / ffmpeg.org/ffmpeg-codecs.html