10

I am attempting to use ffmpeg for a number of files. The actual number of audio streams (there is usually one channel per stream) per file isn't known until I'm using ffmpeg. The desired outcome is to somehow have ffmpeg get the count of audio channel, use the number in the command line to amerge those into one single audio channel. The goal is to create a preview version of the original video file for use in a simple HTML5 page. Is this possible in just one call to ffmpeg? (Also, apologies as some parts of this problem I'm still learning about)

Edit: Dumas stackoverflow asker here. Yes, I've been trying multiple combinations of ffmpeg args. To answer the other question, we have video files that have multiple streams, usually with single channels. I'll post some cmdline examples shortly.

This cmdline example kind of does what I want; there are 8 streams, and I'm able to combine all audio into one. THe issue is having to know the number before running ffmpeg:

ffmpeg -i EXAMPLE.MOV -filter_complex "[0:v]scale=-2:720,format=yuv420p[v];[0:a]amerge=inputs=8[a]" -map "[v]" -map "[a]" -c:v libx264 -crf 23 -preset medium -c:a libmp3lame -ar 44100 -ac 2 OUTPUT.mov
llogan
  • 121,796
  • 28
  • 232
  • 243
wkimbrough
  • 103
  • 1
  • 1
  • 5

2 Answers2

9

The following command should do the same thing as llogan's answer but doesn't recompress the video track and requires you to identify how many audio tracks should be merged together.

If you want to know how many audio streams are present, try:

ffprobe originalfile.mov 2>&1 | grep 'Stream #'

Once you have identified how many audio streams should be merged, use that number in the amerge=inputs=2 parameter here. This command will merge the streams into one and recompress the audio using aac compression.

ffmpeg -i originalfile.mov -c:v copy -c:a aac -b:a 160k -ac 2 -filter_complex amerge=inputs=2 output.mp4
ScottKu
  • 261
  • 2
  • 6
  • 1
    1) `ffmpeg` output is not meant to be machine parsed. Use `ffprobe` instead. 2) No need for `-strict experimental` unless your `ffmpeg` is very old. – llogan Dec 12 '19 at 18:28
  • 1
    Updated the answer to use `ffprobe`. Indeed, I do use some old versions of ffmpeg sometimes. Although there doesn't seem to be harm in including it with recent versions, I removed `-strict experimental` in the answer too. – ScottKu Dec 16 '19 at 17:04
  • 1
    You can eliminate `grep` and just use `ffprobe` alone such as: `ffprobe -loglevel error -select_streams a -show_entries stream=index -of csv=p=0 input.mov` – llogan Dec 16 '19 at 18:42
  • I was looking for a solution to merge the separate mic track of an Nvidia Shadowplay recording with the in-game audio without modifying the video. I read similar answers for `ffmpeg` using `channelmap` that didn't work. But yours finally did! Thank you! – user643011 Jan 18 '22 at 01:54
8

You can use ffprobe to find the number of audio streams and use the output as a variable in your ffmpeg command. Bash example using wc to count the audio streams listed by ffprobe:

ffmpeg -i input.mov -filter_complex "[0:v]scale=-2:720,format=yuv420p[v];[0:a]amerge=inputs=$(ffprobe -loglevel error -select_streams a -show_entries stream=codec_type -of csv=p=0 input.mov | wc -l)[a]" -map "[v]" -map "[a]" -c:v libx264 -crf 23 -preset medium -c:a libmp3lame -ar 44100 -ac 2 output.mov
llogan
  • 121,796
  • 28
  • 232
  • 243
  • 2
    @wkimbrough select this as your preferred answer if it solved your problem. It solved mine. – Adhi Jul 11 '18 at 09:20
  • 1
    The current accepted answer didn't work for me - this one did +1 – scob_ Nov 20 '20 at 20:50
  • The current accepted answer *worked* for me! This one seems to modify the video track. That reduces quality and takes *much* longer. So I can't recommend this solution over the accepted one. But the idea of using the std output of one `ffmpeg` command as an argument to the next `ffmpeg` call via Bash shell is good. – user643011 Jan 18 '22 at 01:58