gstreamer split multi-channel wav file into separate channels and encode each channel as mp3, alac etc and save to file - audio

I need to split a multi-channel wav file and encode each channel into mp3 files.
I know about deinterleave plugin for gtresamer, but I am not sure how to use it for wav file and how to encode the channel stream.
I prefer gtreamer(or ffmpeg) based solution, as I need to limit I/O. I.e, I don't want the intermediate single channel wav files to be written to the storage.
ffmpeg can be used for this in this way. But, both the switches are not available in ubuntu ffmpeg.
snsonic's solutions threw the following error:
(gst-launch-0.10:2218): GStreamer-WARNING **: Failed to load plugin '/usr/lib/gstreamer-0.10/libgstpng.so': libpng12.so.0: cannot open shared object file: No such file or directory
Setting pipeline to PAUSED ...
Pipeline is PREROLLING ...
ERROR: from element /GstPipeline:pipeline0/GstWavParse:wavparse0: Internal data flow error.
Additional debug info:
gstwavparse.c(1982): gst_wavparse_loop (): /GstPipeline:pipeline0/GstWavParse:wavparse0:
streaming task paused, reason not-linked (-1)
ERROR: pipeline doesn't want to preroll.
Setting pipeline to NULL ...
Freeing pipeline ...
(gst-launch-0.10:2218): GStreamer-CRITICAL **: gst_caps_unref: assertion `GST_CAPS_REFCOUNT_VALUE (caps) > 0' failed
When I tested using a single channel wav file without deinterleave, the mp3 file was created but it had only noise.

Do you know the number of channels in advance?
If you use gst-launch you can dome something like:
gst-launch-1.0 filesrc location="xx.wav" ! wavparse ! deinterleave name=d \
d.src_01 ! <encoder> ! filesink location="out1.mp3" \
d.src_02 ! <encoder> ! filesink location="out2.mp3"
and so on. If you don't know the number of channels beforehand, you'll need to write some code.

FFmpeg could probably do what you're asking.

You don't have to know in advance how many channel the wav file has.
You need sox installed.
#!/bin/bash
INPUT=$1
fbname=$(basename "$INPUT" .wav)
N=`soxi -c $INPUT`
for i in $(seq 1 $N)
do
sox ${INPUT} "${fbname}-${i}.wav" remix $i
avconv -i "${fbname}-${i}.wav" -f mp2 "${fbname}-${i}.mp3"
rm ${fbname}-${i}.wav
done
You may want to replace avconv with ffmpeg, depending on the distribution you are working on.

Related

SoX Not Reading Wav

I've got a large (5Gb) WAV 64 file that I'm trying to analyse with SoX. On doing;
sox /file/ -n stats
it tells me;
sox FAIL formats: can't open input file '/file/': WAVE: RIFF header not found
On attempting to specify;
sox /file/ -t w64 -n stats
it says;
sox WARN sox: ignoring `-t w64'.
and proceeds to throw the same error as before. This file is W64. How do I convince SoX to accept it?
Looks like ffmpeg can handle wav64 files
Have you tried to create your own tiny wav64 file and see if you can read that ?
Looks like wav64 is targeted for multichannel audio is that your use case ? WAV format itself is very simple and lends itself to allowing people to write two pages of code to read any wav file ... if you exhaust all other options and your life depended on getting your file read, reading the ISO spec or similar on wav64 format then writing your own reader is an option.
Can you share how your wav64 file was created ? Maybe one of us can replicate its creation and battle how to read it back
If its not full of massive multi-channel audio is getting it converted to normal wav an option ?
Maybe, your wave64 file is invalid. A valid one should contain a riff header.
You've added -t w64 flag after the filename. That's why it's ignored.
# This would work! [CHECKED]
# If your file is valid!
sox -t w64 in_file -n stats

Resample audio file from terminal

I currently have a list of file for which I need to change the sample rate for.
I'recently been aware that this is possible using sox But when I try do it, I keep on getting a error message that sox wav: Premature EOF on .wav input file And causes the audio file to be empty.. it seems like that sox is not able to resample an audio file which input = output... which I kinda need, if I have to convert a whole directory of audio files...
Currently used commands:
~/kaldi-trunk/egs/yesno/s5_k_added$ sox 0_0_0_0_1_1_1_1.wav -r 8000 0_0_0_0_1_1_1_1.wav
sox WARN wav: Premature EOF on .wav input file
:~/kaldi-trunk/egs/yesno/s5_k_added$ play 0_0_0_0_1_1_1_1.wav
0_0_0_0_1_1_1_1.wav:
File Size: 44
Encoding: Signed PCM
Channels: 1 # 16-bit
Samplerate: 8000Hz
Replaygain: off
Duration: unknown
In:0.00% 00:00:00.00 [00:00:00.00] Out:0 [ | ] Clip:0
Done.
How do I resample a directory of audio files?
Try changing the output file name, possible putting it in a different directory if you want to keep the same file name.
For example:
sox 0_0_0_0_1_1_1_1.wav -r 8000 ./out/0_0_0_0_1_1_1_1.wav
I believe sox is attempting to read the file while it is actively changing it, sometimes sox does not create a temporary file to output into.
EDIT: If you have a directory of files you all want to change, use this:
$ mkdir out
$ for file in *; do sox ${file} -r 8000 ./out/${file}; done

Mix .L and .R files into a stereo file using SOX in bulk

I have a folder full of WAV files with separate L and R channels. I've been using SOX for some things like changing the sample rate of the audio files inside a specific folder using this code:
for file in *.wav; do sox $file -r 44100 -b 24 converted/$(basename $file) -V; done
For example, I have these two files that I want to merge:
- CLOSE_1_02.L.wav
- CLOSE_1_02.R.wav
I would like to merge them in a stereo file (L in the left channel and R in the right channel) with the name: "CLOSE_1_02.wav". Can anybody help me?
Thanks.
from link:
sox -M input.l.wav input.r.wav output.wav
will merge input.l.wav and input.r.wav into output.wav.
I'm sorry, but the answer (1) is wrong. The questioner wants a two-channel file with one sound file in the left channel, and the other in the right channel. I tried the command given, and it produces a 1-channel output.wav with both input files mixed into a single channel.

midi to ogg - pipeline distortion

I am trying to convert midi files to ogg or mp3. Eventually this will happen on a linux webserver but currently I am using a Windows 7 machine. I am using timidity to convert the midi to wav and then either sox or ffmpeg to convert the wav to ogg/mp3.
When I use an intermediate file the process works fine (in the first line below timidity creates file.wav)
timidity.exe file.mid -Ow
sox.exe file.wav file.ogg
However, when I try to pipe the timidity output into sox (as below), the resulting file ogg is horribly distorted
timidity.exe file.mid -Ow -o - | sox.exe -t wav - file.ogg
and I get a warning
sox.exe WARN wav: Premature EOF on .wav input file
I also get the same distortion problem when I replace sox with ffmpeg (and the appropriate command line options), or when I replace ogg with mp3 as the output format.
So what am I doing wrong?
Thanks,
Chris
Regarding the warning itself, you're doing nothing wrong. You may also see a warning from timidity that reads something like
Warning: -: Illegal seek: Can't make valid header
What's happening there is explained in the timidity manual page:
If output is directed to a non-seekable file, or if TiMidity++ is interrupted before closing the file, the file header will contain 0xffffffff in the RIFF and data block length fields.
Note that RIFF is the encoding format commonly called by its file extension, .wav. When timidity writes a RIFF file, it doesn't know how long the file will be, so it writes some placeholder junk in the header and moves on to writing the data. When it finishes with the data, it knows how long the file is, so it goes back to the beginning of the file and writes over that junk in the header. When you write to a pipe, it has no way to go back and rewrite anything: the downstream program has to handle the placeholder junk. Also from the timidity manual page:
The popular sound conversion utility sox is able to read such malformed files, so you can pipe data directly to sox for on-the-fly conversion to other formats.
Thus, the message you mentioned. Sox is informing you that the chef prepared the file wrong BUT SOX IS HAPPY TO EAT IT ANYWAY BECAUSE SOX IS NOT PICKY. Sox is apparently passive-aggressive. Who knew?
You can ignore those warning messages, because now they are telling you something you already know. Or, you can use a raw format and explicitly tell timidity and sox how to play well with one another:
timidity file.midi -Or1Ssl -s44.1 -o- | sox -t raw -b 16 -e signed -r 44.1k -c 2 - file.ogg
As for the distortion, that may be caused in part by quirks in the audio libraries on the Windows system. I note that the pipeline in the question, sans .exe extensions, produces output with no notable distortion on a linux system. Using a well-defined raw format in the pipeline may also help with that issue.
Note that for Ogg output, you can now get that directly from timidity:
timidity file.midi -o file.ogg -Ov

Find if video file has audio present in it [duplicate]

This question already has answers here:
Using ffprobe to check if file is audio or video only
(5 answers)
Closed 5 years ago.
I'm trying to figure out if a video has audio present in it so as to extract the mp3 using ffmpeg. When the video contains no audio channels, ffmpeg creates an empty mp3 file which I'm using to figure out if audio was present in the video in the first place. I'm sure there is a better way to identify if audio is present in a video. Will avprobe help with this? Can anyone point me to a resource or probably a solution?
Edit: Surprisingly, the same command on my server running the latest build of ffprobe doesn't run. It throws an error saying
Unrecognized option 'select_stream'
Failed to set value 'a' for option 'select_stream'
Any ideas how to rectify this out?
I would use FFprobe (it comes along with FFMPEG):
ffprobe -i INPUT -show_streams -select_streams a -loglevel error
In case there's no audio it ouputs nothing. If there is an audio stream then you get something like:
[STREAM]
index=0
codec_name=mp3
codec_long_name=MP3 (MPEG audio layer 3)
profile=unknown
codec_type=audio
codec_time_base=1/44100
etc
etc...
[/STREAM]
That should be easy enough to parse regardless of the language you're using to make this process automated.
If it is normal video file from the local path, you can do something like this to find whether video has audio file or not.
You need to look into the MediaMetadataRetriever
By using METADATA_KEY_HAS_AUDIO you can check whether the video has the audio or not.
private boolean isVideoHaveAudioTrack(String path) {
boolean audioTrack =false;
MediaMetadataRetriever retriever = new MediaMetadataRetriever();
retriever.setDataSource(path);
String hasAudioStr = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_HAS_AUDIO);
if(hasAudioStr.equals("yes")){
audioTrack=true; }
else{
audioTrack=false; }
return audioTrack;
}
Here path is your video file path.
PS: Since it is old question , i am writing this answer to help some other folks , to whom it may help.
Found a round about to solve this problem. This seems to answer the question I asked.
ffprobe -i input.mp4 -show_streams 2>&1 | grep 'Stream #0:1'
ffprobe -v fatal # set log level to fatal
-of default=nw=1:nk=1 # use default format and hide wrappers and keys
-show_streams # show info about media streams
-select_streams a # show only audio streams
-show_entries stream=codec_type # show only stream.codec_type entries
video.mp4 # input file
A media file contains an audio stream returns:
audio
1
0
0
0
0
0
0
0
0
0
0
0
und
SoundHandler
A media file contains no audio stream retuns empty result.
A non-media file also returns empty result. If you want to return an error message for non-media files and on any other error case, use -v error instead:
ffprobe -v error # set log level to error
-of default=nw=1:nk=1 # use default format and hide wrappers and keys
-show_streams # show info about media streams
-select_streams a # show only audio streams
-show_entries stream=codec_type # show only stream.codec_type entries
video.mp4 # input file
So, you take this instead of empty result:
non-media-file.zip: Invalid data found when processing input
If you only want to know if there is audio and don't care about the stream details you can run the following command, which will extract the duration of the audio stream in the input file. If the response is null/whitespace the input file has no audio in it.
Command:
ffprobe -v error -of flat=s_ -select_streams 1 -show_entries stream=duration -of default=noprint_wrappers=1:nokey=1

Resources