FFmpegで変換したら「映像はあるのに音が出ない」「複数あったはずの音声トラックが1本に減っている」という事故は非常によく起きます。原因は大きく4つに絞れます。本記事では、まず ffprobe で状況を確認し、原因を1つずつ切り分けて確実に直す手順を解説します。

動作確認: ffmpeg 6.1 で確認済み


この記事でわかること

  • 出力から音声が消える「典型的な4つの原因」と、それぞれの直し方
  • ffprobe を使って「入力に音声があるか・何トラックあるか」を最初に確認する方法
  • -map のマップ漏れ、-an の混入、コンテナ非対応コーデック、複数トラックの既定挙動という4パターンの切り分け
  • 0:v:0 0: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 にコーデック aac2 チャンネルの音声トラックが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

コンテナごとの音声コーデック対応の目安は次の通りです。

コンテナ対応しやすい音声コーデック備考
MP4AAC / MP3 / AC3Opus は限定的。基本は AAC へ再エンコード
MKVほぼ何でも(AAC/Opus/Vorbis/FLAC/AC3…)困ったら MKV にすれば -c copy で通ることが多い
WebMOpus / 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:01番目の入力の、1番目の映像ストリーム
0:a:11番目の入力の、2番目の音声ストリーム
0:a1番目の入力の、すべての音声ストリーム
1:a:02番目の入力の、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