78

I want to concatenate multiple WAV files into a single WAV file using FFMPEG.

I have used the following command and it generates the required file.

Command:

ffmpeg -f concat -i mylist.txt -c copy output.wav

File :

#mylist.txt
file '1.wav'
file '2.wav'
file '3.wav'
file '4.wav'

But as you can see the problem is that I have to create a text file to specify the list of WAV files to concatenate.

I can do all these tasks, but I would prefer a single command something that looks like

ffmpeg -i 1.wav -i 2.wav -i 3.wav -i 4.wav output.wav 

or

ffmpeg -i "concat:1.wav|2.wav|3.wav|4.wav" -c copy output.wav

I have tried these two simple commands but they return just the voice of 1.wav Please help me write a single command( or correct the above 2 commands ) that achieves the desired result.

Please don't suggest other Media Encoders/Editors, I want to use FFMPEG only, as it is already installed and used at other places.

1

7 Answers 7

67

You could try using the concat filter; it requires re-encoding, and so will take more system resources (a pretty tiny amount on any vaguely modern computer in this particular case), but PCM -> PCM audio should be mathematically lossless. In your case, you would use something like:

ffmpeg -i input1.wav -i input2.wav -i input3.wav -i input4.wav \
-filter_complex '[0:0][1:0][2:0][3:0]concat=n=4:v=0:a=1[out]' \
-map '[out]' output.wav

For example if you have five input files, use n=5 and add [4:0].

4
  • 8
    Note: Don't customize [0:0][1:0][2:0][3:0] to match the number of files. Use that exactly as it says. The only thing you should change is the input files and n=4.
    – Keavon
    Mar 7, 2015 at 22:40
  • 19
    @Keavon: are you sure? Here ffmpeg (version N-49352-gc46943e x64) complains Too many inputs specified for the "concat" filter. when I try to process only 2 inputs with the original code. It works though when I remove [2:0][3:0]... which makes sense to me since in this case there are no such things as streams 2:0 and 3:0... Apr 22, 2016 at 19:03
  • 5
    I agree with @BigueNique. I too ran into the same error and though it feels a little silly, wrote some code to generate the proper sequence given n.
    – Ryan DuVal
    May 12, 2019 at 18:54
  • 1
    Please bear in mind that on Windows, you should use double quotes " instead of single quotes ' above, it took me some figuring, hope it spares you the trouble
    – mxl
    Dec 29, 2021 at 14:43
54

I think the best option for wav is to use sox, not ffmpeg:

$ sox short1.wav short2.wav short3.wav long.wav

Solution comes from How do I append a bunch of .wav files while retaining (not-zero-padded) numeric ordering?

If you have many wav files in the current dir

$ sox '*' long.wav

Warning, the last file named in sox gets overwritten, so in this case - if long.wav exists, it will be destroyed and then made new from the others.

4
  • 7
    Question was precisely about .wav Mar 16, 2018 at 7:13
  • 4
    the question explicitly stated that a solution is required using ffmpeg only!
    – Manu
    Apr 3, 2018 at 8:00
  • sox can support .mp3 files too
    – Benjamin
    May 28, 2018 at 18:55
  • 3
    Be sure to put your desired output-file-name on the end of that argument list or you'll overwrite the last file listed! Luckily, I had another copy. Pressing enter too soon with sox is dangerous. It worked good for me, though. Thanks Héctor!
    – LonnieBest
    Sep 26, 2018 at 6:00
24

The FFmpeg wiki mentions using the concat protocol is not possible with all file types. It works fine with most MPEG containers and bitstreams, but obviously not WAV files with PCM audio.

You don't necessarily have to create a temporary file and use that. With Bash (or other shells that support process substitution), you can do everything in a single command:

ffmpeg -f concat -i <( for f in *.wav; do echo "file '$(pwd)/$f'"; done ) output.wav

The process substitution <( ) creates a file—or, to be precise, a file descriptor—on the fly, which ffmpeg can read. This file will contain the path to every .wav file in the current directory. We have to prefix it with $(pwd) to get the correct path relative to your current directory, and not relative to the file descriptor.

Of course, the command within the substitution can be changed to something else.

2
  • 7
    If you get Unsafe file name error you would need -safe 0 option before -i. ref. stackoverflow.com/q/38996925/297679
    – Nobu
    Nov 27, 2017 at 21:07
  • If you want to change the bitrate for instance to 320, append -b:a 320k before output.wave
    – Niklas
    Nov 18, 2022 at 12:00
6

Another option is to use concat

ffmpeg -i "concat:file1.mp3|file2.mp3|file3.mp3" -acodec copy out.mp3

6
  • 1
    Welcome to superuser: While this may or may not answer the question,(an answer has been accepted) it would be a better answer if you could provide some explanation why your solution works with detail and an easy to follow instructions. If you feel your answer is correct do these things and re-edit. Please take a couple of minutes and read:- superuser.com/help .Answering: superuser.com/help/how-to-answer, again welcome to superuser.Thankyou
    – mic84
    Mar 24, 2018 at 7:34
  • 3
    I tested this and it does not appear to work
    – Nick Long
    Aug 7, 2019 at 13:56
  • 8
    This does not work. It only ends up using the first file.
    – Brad
    Dec 28, 2019 at 21:43
  • 1
    I also tested it and it also only ends up using the first file. Feb 20, 2020 at 4:45
  • 1
    this only works
    – S. Kr.
    Mar 1, 2020 at 16:12
4

In Win8's Cmd.EXE .BAT script:

Rem Get number of source files
For /F %%A In ('Dir *.3gp /B /A-D ^| Find /C /V ""') Do      Set FilCnt=%%A

Rem Build list of source filenames
Set Lst=
For    %%A In (     *.3gp                          ) Do Call Set Lst=%%Lst%% -i %%A

Rem Concat and Convert sources to target
FFMPeg.EXE %Lst% -filter_complex concat=n=%FilCnt%:v=0:a=1 -vn Output.OGG

This way, you don't bother with the source file names or the concat-count parameter.

4

I seen people posting similar answers, but never this exact answer which works great.

sox "file*" output.wav

The above command will combine all the files and use the * symbol as a wildcard. You use the quotes to avoid having your shell perform the expansion. Instead we let sox perform the expansion that way any of your parameters will be applied to every audio file.

4
  • 1
    Does sox guarantee a specific order of processing the files?
    – Arjan
    Apr 1, 2020 at 12:02
  • 1
    @Arjan Actually, sox isn't determining the order of the files. It's the command interpreter, i.e. bash. If you type echo file*, you'll see how the interpreter expands the expression to send to the program.
    – pkSML
    Sep 2, 2023 at 12:26
  • @pkSML Maybe I’m missing something here Goddard is explicitly saying that sox is doing the expansion, not the shell. Do you mean any program will forcibly expand the expression in the same manner?
    – Stéphane
    Jan 11 at 18:31
  • 1
    @Stéphane Yes, upon a more careful reading, @Goddard is correct. If you don't put file* in quotation marks, the bash shell expands it. With quotation marks, the string gets passed verbatim to sox, and sox performs the expansion. My mistake... Anyways, sox gets the files in correct order when using sequential extensions (i.e. file.wav.001, file.wav.002, etc.) from my experience, to answer the question from @Arjan.
    – pkSML
    Jan 12 at 2:59
-1

You could use shntool for wav-files.

shnjoin -r none 01.wav 02.wav ...

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .