Script to convert sample rate of audio file in Ubuntu - bash

ls -lrt *wav|wc -l --> 2160
Got around 2k audio files with sample rate 8k. Need to make an script to convert all the files to 16k Sample rate.For now Usig SOX for converting 1 file at a time.
For eg. :-
sox 9560850166.wav -r 16000 -b 16 -c 1 file1.wav
Need an script so that next audio files will be selected from the directory and SOX will be done to change sample rate and it will be saved with a new file name like file1.wav, file2.wav etc...

Run the below for loop from the directory containing wave files
a=0;
for i in `ls *.wav`;
do
let a++;
echo "Processing file $i"
sox $i -r 16000 -b 16 -c 1 file$a.wav
done

You do not need a script for this combination of find and exec will do the job
Use following command
find ./ -name "*wav" -exec sox {} -r 16000 -b 16 -c 1 {}.16000.wav \;
With this new audio file should get created with .16000.wav appended in original file name.

#!/bin/bash
i=0;
for filename in /home/mrityunjoy/myWork/audio_files/*.wav; do
i=$((i+1));
sox "$filename" -r 16000 -b 16 -c 1 "file$i.wav"
done
This will give the output in the directory we run the script.

Related

Using afconvert command line tool to convert .mp3 files to m4r

I have a short bash script that is meant to convert a folder full of .mp3 files to .m4r ringtones. I am having trouble figuring out why it is throwing the following error:
"Error: ExtAudioFileCreateWithURL failed ('fmt?')"
#!/bin/bash
cd "/path/to/directory/containing/mp3s"
for i in *.mp3; do
baseFilename=$( basename ${i} .mp3 )
afconvert -f m4af ${i} -o "/path/to/new/location/${baseFilename}.m4r"
done
exit 0
The issue was that I had not specified the output data format. Found a helpful page that lead me to the answer:
http://support.moonpoint.com/os/os-x/audio/afconvert.php
#!/bin/bash
cd "/path/to/directory/containing/mp3s"
for i in *.mp3; do
baseFilename=$( basename "${i}" .mp3 )
afconvert -f m4af "${i}" -d aac "/path/to/new/location/${baseFilename}.m4r"
done
exit 0

How to change sample rate for all files in a directory

How do I change the sample rate for every file in the folder?
I have the following code and it just erases the files -- the file size becomes 0.
for i in wav/*.wav; do
sox -r 8000 -e unsigned -b 16 -c 1 "$i" "$i"
done
Why is that?
sox -r 8000 -e unsigned -b 16 -c 1 "$i" "$i"
Your not using $o (the output file) anywhere - looks like you're trying to input and output from the same file (just a guess - not familiar with sox)
One approach would be to write to a temporary output file and then move that over the top of the input file:
for fname in wav/*.wav; do
TMP_OUT=$(mktemp)
sox -r 8000 -e unsigned -b 16 -c 1 "$fname" $TMP_OUT
mv $TMP_OUT $fname
done
The danger here is that you lose the input file if something goes wrong. I would check the result of sox and only overwrite the input file if sox was successful.

Return variable from website Bash command

I used to have a script which basically, returned the current temperature from a website. This was done with wget then awk to return the "Temperature" as a variable then I used sox to create a file saying the Temperature is etc.
The website has changed and I am having trouble re-writing it.
This is what I have:
URL='https://wttr.in/rhyl'
temp="wget -q -O- "$URL" | awk -F\' 'data-value/{print $1 }'| head -1)"
sox -V1 -c 1 silence.wav base.wav $temp.wav temp-dry.wav
sox -V1 -m temp-bed2.wav temp-dry.wav tempfx.wav
sox -V1 tempfx.wav tempfx+15db.wav vol 9 db
sox -V1 temp-dry.wav temp-dry+10db.wav vol 10 db
I'm happy with the sox bit so far, I just cant seem to return the variable i.e. "12" from the temperature section of wttr.in
The desired output of $temp is just number no special characters i.e $temp = 12
temp="wget..." is just storing the string "wget..." in the variable temp, it's not executing the command wget... if that's what you intended there then you should be doing temp="$(wget...)" instead. Try temp="$date"; echo "$temp" vs temp="$(date)"; echo "$temp" to see the difference.
This is a version bash file that updates and audio file for the current temperature, for the radio station jingle.
#/////Get weather for where you want thanks to User3439894 and Bengamin W. /////
temp="$(curl -s https://wttr.in/rhyl?format=%t | grep -Eo [0-9]+)"
# ////use sox to make the dry file outof pre-defind wav files/////
sox -V1 -c 1 silence.wav base.wav $temp.wav temp-dry.wav
# //// Here I use sox again to create a wav file with start and end jingle /////
sox -V1 -m temp-bed2.wav temp-dry.wav tempfx.wav
# //// Using sox again I boost the audio by what is required 15db and 10 db///
sox -V1 tempfx.wav tempfx+15db.wav vol 9 db
sox -V1 temp-dry.wav temp-dry+10db.wav vol 10 db
I then use crontab to run this bash script as a cronjob.
thanks everyone
Alex

List files in a folder in natural order using bash script

I am trying to merge several flv files using ffmpeg. ffmpeg requires a list of files in this format:
file '/path/to/file1'
file '/path/to/file2'
file '/path/to/file3'
With some search and trials, I have came up with this one line command:
ffmpeg -safe 0 -f concat -i <(for entry in "$(cd "$(dirname "$1")"; pwd)/$(basename "$1")"/*.flv;do echo "file '$entry'";done) -c copy output.flv
The script in brackets will generate a list of paths to all files in current folder in the format that is required by ffmpeg:
for entry in "$(cd "$(dirname "$1")"; pwd)/$(basename "$1")"/*.flv;do echo "file '$entry'";done
However, this only list files in alphanumeric order:
6846641-10.flv
6846641-11.flv
6846641-12.flv
6846641-13.flv
6846641-14.flv
6846641-15.flv
6846641-16.flv
6846641-17.flv
6846641-18.flv
6846641-19.flv
6846641-1.flv
6846641-20.flv
6846641-21.flv
6846641-22.flv
6846641-23.flv
6846641-24.flv
6846641-2.flv
6846641-3.flv
6846641-4.flv
6846641-5.flv
6846641-6.flv
6846641-7.flv
6846641-8.flv
6846641-9.flv
To merge videos correctly, I need files to be listed in natural order like this:
Naturally ordered files
As shown in the picture, files need to be sorted by the number after - from 1 to 24, with 6846641-1.flv in the first line and 6846641-24.flv in the last line. And each line in the format like this:
file '/mnt/c/Users/Oho/Desktop/save//6846641-xx.flv'
Would it be possible to generate a correctly formatted list for ffmpeg with bash script (and in one line if achievable)?
Edit:
Thanks to Cyrus, the modified code is here and it does the job:
#!/bin/bash
for entry in "$(cd "$(dirname "$1")"; pwd)/$(basename "$1")"/*.flv
do
echo "file '$entry'" >> fileOutputList.temp
done
sort -t "-" -n -k 2 fileOutputList.temp > fileOutputListSorted.temp
ffmpeg -safe 0 -f concat -i fileOutputListSorted.temp -c copy output.flv
rm fileOutputList.temp
rm fileOutputListSorted.temp
I suggest:
sort -t "-" -n -k 2 file
-t "-": use - as separator
-n: compare according to string numerical value
-k2,2: start a key at column 2

Reroute File Output to stdout in Bash Script

I have a script, wacaw (http://webcam-tools.sourceforge.net/) that outputs video from my webcam to a file. I am trying to basically stream that to some sort of display i.e vlc, quicktime, etc to get a "mirror" type effect.
Aside from altering the source code for wacaw, is there any way to force a script's file output to stdout so I can pipe it to something like vlc? Is it even possible to stream video like that?
Thanks for your help!
UPDATE: just to clarify:
running the wacaw script is formatted as follows:
./wacaw --video --duration 5 --VGA myFile
and it outputs a file myFile.avi. If I try to do a named pipe:
mkfifo pipe
./wacaw --video --duration 5 --VGA pipe
it outputs a file pipe.avi
You can use named pipes. You use mkfifo to create the pipe, hand that filename to the writing process and then read from that file with the other process. I have no idea if video in particular would work that way, but many other things do.
At least in bash you can do like this:
Original command:
write-to-file-command -f my-file -c
Updated command:
write-to-file-command -f >(pipe-to-command) -c
write-to-file-command will think >(pipe-to-command) is a write-only file and pipe-command will receive the file data on its stdin.
(If you just want the output to stdout you could do
write-to-file-command >(cat)
)
You may also try using tail -F myFile.avi:
# save stdout to file stdout.avi
man tail | less -p '-F option'
(rm -f myFile.avi stdout.avi; touch myFile.avi; exec tail -F myFile.avi > stdout.avi ) &
rm -f myFile.avi; wacaw --video --duration 1 --VGA myFile
md5 -q myFile.avi stdout.avi
stat -f "bytes: %z" myFile.avi stdout.avi
# pipe stdout to mplayer (didn't work for me though)
# Terminal window 1
# [mov,mp4,m4a,3gp,3g2,mj2 # ...]moov atom not found
#rm -f myFile.avi; touch myFile.avi; tail -F myFile.avi | mplayer -cache 8192 -
# Terminal window 2
#rm -f myFile.avi; wacaw --video --duration 1 --VGA myFile

Resources