15

What command-line tools do I need in order to concatenate several audio files and output them as one ogg (and/or mp3)?

If you can provide the complete command to concatenate and output to ogg, that would be awesome.

Edit: Input files (in my case, currently) are in wma format, but ideally it should be flexible enough to support a wide range of popular formats.

Edit2: Just to clarify, I don't want to merge all wmas in a certain directory, I just want to concatenate 2 or 3 files into one.

Thanks for the proposed solutions, but they all seem to require creating temporary files, if possible at all, I'd like to avoid that.

3
  • 1
    what input formats do you need support for?
    – user1931
    Nov 2, 2009 at 1:19
  • In principle, you can tweak all these commands to pipe output between each other. But practically, it's a pain to get it working, and a pain to debug when it fails. There are practical ways to do temp files. My preferred method is to use mktemp -d /tmp/descriptive_name.XXXXXX to create a temporary directory with an informative name, then process all my temp files in there, then rm -r the temp dir afterward. Nov 2, 2009 at 7:41
  • just to clarify, anything that works for all wma's in a directory, by specifying *.wma in a commandline, will certainly work for a smaller list like 1.wma 2.wma 3.wma 4.wma (leaving out 5.wma, 6.wma, & 7.wma), simply by listing them out like that (instead of using *.wma). Nov 2, 2009 at 13:19

9 Answers 9

9

Here's my suggestion: Use mplayer and oggenc connected with a named pipe.

  • Use mplayer to decode the audio. It can play back a wide variety of audio (and video) formats, and it also can play multiple files.

  • Use oggencto encode the audio to Ogg Vorbis.

  • To eliminate the need for a temporary file, use a named pipe to transfer the data between encoder and decoder.

Putting that into a script:

#!/bin/sh
# Usage: ./combine2ogg destination.ogg source1.wma source2.wma ...
# Requires: mplayer, oggenc
destination="$1"
shift
readpipe="$destination.tmpr"
writepipe="$destination.tmpw"
mkfifo "$readpipe"
mkfifo "$writepipe"
cat "$writepipe" > "$readpipe" &
mplayer -really-quiet -slave -nolirc -vc null -vo null -ao "pcm:fast:file=$writepipe" "$@" &
oggenc --quiet -o "$destination" "$readpipe"
rm -f "$readpipe"
rm -f "$writepipe"

Explained:

  1. Take the destination file name from the first command line parameter.
  2. Remove the first command line parameter, leaving only the source file names.
  3. Create a name for a pipe for oggenc to read from.
  4. Create a name for a pipe for mplayer to write to
  5. Create the pipes.
  6. Use cat to continuously dump the writepipe to the readpipe (this helps avoid issues where mplayer may terminate, but prevents oggenc from thinking it's done when this happens)
  7. Decode the audio from the source files using mplayer. Options -really-quiet -slave -nolirc are there to disable messages and to make it not read the keyboard or the remote. Options -vc null -vo null are there to disable video encoding and output. The -ao option directs it to output the audio in WAV format to the named write pipe.
  8. While the previous command is running, simultaneously encode from the named read pipe into Ogg using oggenc.
  9. Remove the named pipes.

Stuff to left to improve: Terminating the script early if one of the commands fails (use set -e), but still properly cleaning up the fifo (trap the necessary signals).

2
  • The only "slight" problem is there's a click sound between files
    – hasen
    Nov 2, 2009 at 21:44
  • @hasen j: if you want perfect, use Audacity or another wav-editor. if you can track down the source of the click, you could file a bugreport on the offender. Nov 2, 2009 at 23:02
17

SoX can handle a large number of audio formats, depending on what libraries it's compiled against, and can concatenate files with a simple command line

sox file1.wav file2.mp3 file3.flac outfile.ogg

I believe this only works if the source audio files all have the same number of channels, but I've not tested this.

As far as I know, SoX has zero support for .wma files, so converting at least those files with something like ffmpeg first is probably unavoidable.

ffmpeg -i infile.wma outfile.wav
1
  • 3
    AFAIK sox only works like that if all files have the same channels, sample rate, & bit depth; otherwise you have to specify for all. i didn't realize it would decode encoded formats too, but i guess i haven't been keeping up with it. Nov 2, 2009 at 13:17
4

I would use ffmpeg. To convert wma to ogg vorbis try:

ffmpeg -i sample.wma -acodec vorbis -aq 100 sample.ogg

or mp3:

ffmpeg -i input.wma -acodec libmp3lame output.mp3

you'll need lame installed for the mp3 convert. sudo apt-get install lame libmp3lame0

Cat, then convert doen't seem to work well, although you can find lots of references on the web saying you can do something like cat *.wma | ffmpeg -i - -acodec ... - this doesn't work on my machine - only the first file gets processed. There is a 'copy' codec for ffmpeg, but doesn't make much difference.

Doing the convert with ffmpeg first, then cat *.ogg > output.ogg worked for me.

3
  • 1
    ok, what about concatenation?
    – hasen
    Nov 2, 2009 at 2:33
  • sorry about that! Read my additions. Nov 2, 2009 at 2:52
  • not so sure about ffmpeg... fine as a WMA decoder, but lots of complaints about the OGG encoder. at least use -acodec libvorbis to avoid ffmpeg's builtin encoder. Nov 2, 2009 at 4:59
4

To concatenate and transcode audio files, this is the workflow you want to follow:

  1. Decode input audio files to WAV/PCM data,
  2. Concatenate WAV,
  3. Encode WAV to output audio codec file.

Processing in these steps performs the concatenation on the WAV data, which is the easiest to deal with and least lossy. And since you want to transcode anyway, you'll have to decode to WAV somewhere in the process; might as well take advantage of it.

Here are the steps I recommend. We'll use ffmpeg for decoding, sox for concatenation, and oggenc for encoding. You could substitute other tools for any step -- mencoder and others work fine as a decoder, and any tool that encodes Ogg can be used as the encoder -- although I think you'll be hard-pressed to find a better tool than sox for the concatenation.

  1. find *.wma -exec ffmpeg -i {} outfile.{}.wav \;
    (this runs ffmpeg -i infile.wma outfile.infile.wma on each WMA file in the current directory)

  2. sox outfile* all.wav
    (note outfile is the same prefix we gave the output files in step 1)

  3. oggenc all.wav all.ogg you probably want some quality settings here, but this will give decent quality defaults. I did not get results I liked with ffmpeg, but you may prefer it, so I've included an example with ffmpeg below.

Note that the sox command won't work properly unless all the WAV files are the same format -- if some are 22kHz and some are 44.1kHz, for example, you need to identify them to sox via commandline switches, and specify which format you want the output in. I don't know any commandline tools as capable as sox for the concatenation step. You could possibly output to a raw PCM format in step 1 and use cat for step 2, but that would only work if they're in the same format, and you'd need to be extremely specific to both your decoder and encoder as to what format they should expect.

Encoding with ffmpeg: Lots of posts around the 'net complain that ffmpeg's builtin Vorbis encoder isn't very good. If your version is built with libvorbis support, use -acodec libvorbis instead. Sample commandline:

ffmpeg -i all.wav -acodec libvorbis -ac 2 -ab 128k all.ogg
1

Won't work for .ogg files, but mp3wrap can concatenate multiple .mp3 files into a single file. So from the command line, you could do something like this

for FILE in *.wma; do ffmpeg -i "$FILE" "`basename "$FILE" .wma`.mp3"; done
mp3wrap bigmp3_MP3WRAP.mp3 *.mp3

This will use ffmpeg to convert all your .wma files into .mp3, and then merge all the .mp3 files into a single file.

1

Mencoder can concatenate and transcode videos without temp files (trivial example here). There's a script floating around somewhere called aconvert that tricks mencoder into doing audio-only (which it normally refuses to do). These two things combined seem like they would satisfy your requirements.

Edit: I found aconvert.sh. Unfortunately, it's only designed to convert one audio file. But here's the code anyway, in case anyone wants to use it to craft a command line that converts multiple audio files.

#!/bin/sh

# Author: Jonas Jermann
# Description: A hack to allow mencoder to encode from an audio only file

if [ "$1" = "" ]; then
    echo "Usage: $0 <\"input file\"> <\"output file\"> <\"options\">"
    exit 0
fi

options=${3:-"-oac mp3lame"}

mencoder -demuxer rawvideo -rawvideo w=1:h=1 -ovc copy -of rawaudio -endpos `mplayer -identify $1 -frames 0 2>&1 | grep ID_LENGTH | cut -d "=" -f 2` -audiofile $1 -o $2 $options $1
0

This might not be exactly what you need, but it should help http://bitzenbytes.com/index.php?name=PNphpBB2&file=viewtopic&t=6538&postdays=0&postorder=asc&sid=f87b364ddbae3ddd9417f5d10fae870c

0

Thought I'd throw my answer in. This probably isn't the most elegant way, but it did what I wanted.

Step 1: convert to ogg (uses mplayer, pacpl and ruby, all available from the free Debian repos. I)

#! /usr/bin/ruby

ARGV.each do |target|
  file_ext = target.scan(/\.\w*$/)[0]
  name = target.sub(file_ext, "")

  `mplayer -novideo -ao pcm:file="tmp.wav" "#{target}"`
  `pacpl -t ogg --outfile "#{name}" tmp.wav`
  `rm tmp.wav`
end

Step 2: concatenate ogg files

cat *ogg > big-file.ogg
0

cat file list… | ffmpeg -f mp3 -i – -acodec copy outfile.mp3 worked nicely for me with MP3s: I imagine it would work with other formats as well. Credits go to Lindylex.

You must log in to answer this question.

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