Mac shell script to extract audio from video files - macos

I'm trying to write a shell script that will extract the audio from all the movie files in a folder.
audio_extracter.sh
for f in *; do
if [ "$f" != "audio_extracter.sh" ]; then
/usr/bin/avconvert --source "$f" --output */Converted/"$f" --audioTrack -af aac
echo "$f converted"
else
echo "problems"
exit 1
fi
done
It's spitting back avconvert is a command line application that will transcode a source or group of sources to create a destination file output...
Also, if possible the script should find out the format of the audio in the video and extract it as such, without converting it to a different different format (at the moment I think I'm forcing it to convert to AAC).
Any thoughts on how to make this work?

-acodec copy extracts audio without re-encoding in ffmpeg:
for f in *.mkv; do ffmpeg -i "$f" -acodec copy "${f%mkv}aac"; done
You can see the formats of the audio streams with ffmpeg -i input.mkv.

If you can use mencoder, then try this. It works for me. (video format like mkv, mp4, flv, rmvb all works)
mencoder -oac mp3lame -ovc copy -of video_file -o audio_file.mp3

Related

Batch .SRT Rip Using FFMPEG

I have this command using ffmpeg
root#ubuntu-4cpu-8gb-sg-sin1:/home/jaac/torrents/rtorrent/dots# ffmpeg -i Title.NF.WEB-DL.DDP2.0.x264-Ao.mkv -map 0:7 indo16.srt
That will rip 1 sub (Indonesia region)
How to rip it in batch? I have 17 files in dots folder
Thanks
Run these commands:
cd /home/jaac/torrents/rtorrent/dots
for f in *.mkv; do ffmpeg -i "$f" -map 0:s:m:language:ind "${f%.*}.srt"; done
Adapted from How do you convert an entire directory with ffmpeg?
What the -map option is doing: 0:s:m:language:ind is input #0: subtitles:metadata:language:indonesian. Which means it chooses all subtitle streams from the input that have Indonesian language metadata.
If you get error:
Stream map '0:s:m:language:ind' matches no streams.
To ignore this, add a trailing '?' to the map.
You can ignore it. Just a message telling you there is no subtitle stream with Indonesian language metadata in that particular input.
You can use a for loop:
for f in *.mkv; do ffmpeg -i $f -vf subtitles="${f%.mkv}".srt "${f%.mp4}"_sub.mkv; done
Subtitules files must have the same name as videos.
Thanks guys for helping me out.
I use this command to batch rip the subtitle:
#!/bin/bash
cd /home/jaac/torrents/rtorrent/dots || exit
for f in *.mkv; do ffmpeg -i "$f" -map 0:5:s:m:language:id "${f%.*}.srt"; done
I use Shellcheck
Thanks #llogan and #m8factorial

Batch extracting frames from multiple mp4 file

So i have a folder with only mp4 files. I just want to get specific frames for every mp4 files automatically. I tried the below command, but it tried overwriting the mp4 file, is there any error with the below command? So i expect to input a mp4 file and to get 3 frames in .jpg format.
for i in *.mp4; do
ffmpeg -i *.mp4 -vf select='eq(n\,10)+eq(n\,17)+eq(n\,21)' -vsync 0 frames%d.jpg
done
I am no expert on ffmpeg but you have some fairly fundamental issues in your script. Hopefully, this will get you started:
for i in *.mp4; do
ffmpeg -i "$i" -vf select='eq(n\,10)+eq(n\,17)+eq(n\,21)' -vsync 0 "${i%.*}_frames%d.jpg"
done

Ffmpeg Ignore stream if it doesn't exist

I'm using ffmpeg to convert files to .mp3 and extract cover images from the metadata.
This works fine for files that have cover images, files that don't throw the error:
Output #1 does not contain any stream
ffmpeg -i kalimba.mp3 -y test.mp3 -acodec copy test.jpg
How can I tell ffmpeg to just ignore streams if they don't exist and continue converting to .mp3 if no cover image exists in the metadata?
First you should check what streams are provided in the file. You can do it with tool ffprobe. Then you run ffmpeg to copy one or two streams.
if [ -n "`ffprobe -show_streams -v quiet kalimba.mp3 | grep '^\[streams\.stream\.1\]'`" ] ; then
# the file has 2 streams
ffmpeg -i kalimba.mp3 -y test.mp3 -acodec copy test.jpg
else
# no cover image
ffmpeg -i kalimba.mp3 -y test.mp3 -acodec copy
fi

Concat multiple video and audio files with ffmpeg

I have an array of audio and video clips, where each audio clip has a 1:1 correlation with it's video clip. The encoding of each video and each audio clip are the same. How can I concat all of the audio clips, and all the video clips, then merge them together to output a video. As of now I only figured out how to merge 1 audio clip with 1 video clip:
$ ffmpeg -i video_1.webm -i audio_1.wav -acodec copy -vcodec copy output.mkv
Update
I just came across mkvmerge would this possibly be a better option?
If all the files are encoded with the same codecs then it's easy to do. First merge the audio and video files as you have already done so each pair of files is contained in one mkv. Then you can concatenate them with the concat demuxer like this:
ffmpeg -f concat -i <(printf "file '%s'\n" ./file1.mkv ./file2.mkv ./file3.mkv) -c copy merged.mkv
or:
ffmpeg -f concat -i <(printf "file '%s'\n" ./*.mkv) -c copy merged.mkv
You could also list one file per line in a text file called mergelist.txt (or whatever you want to call it), i.e.:
file './file1.mkv'
file './file2.mkv'
file './file3.mkv'
Then use that as the input, a la:
ffmpeg -f concat -i mergelist.txt -c copy merged.mkv
This is by far the easiest and fastest way to do what you want since it won't re-encode the files, just line them up one after another.
You can find your answer here in this old question:
Concatenate two mp4 files using ffmpeg
This answer is not restricted to MP4. But it will depend on the file format you wanna concatenate!
Once you have your new VIDEO file and AUDIO file, to merge them together:
ffmpeg -i AUDIO -i VIDEO -acodec copy -vcodec copy OUTPUT

How can I automatically convert all MP4 files to FLV with ffmpeg?

How can I automatically convert all MP4 files to FLV in a specific folder?
ffmpeg -i VID00002.MP4 -ar 44100 test.flv
Is there a way to queue these tasks, assuming that I don't know the file names?
If I need to run any scripts (I'm familiar with Python), how can I do that?
You can do this fairly easy within the terminal, given you have ffmpeg installed. In your terminal, enter the following:
$>cd /your/path/to/videos
$>for i in *.mp4; do ffmpeg -i $i -ar 44100 $i.flv; done
The second command simply iterates through each mp4 file and assigns the filename to '$i'. You then call ffmpeg using $i as the input and output filename. For the output, you simply add the extension, in this case $i.flv. So, if your filename is 'video.mp4', it will output as 'video.mp4.flv'.
Hope this helps.
This will convert and rename the new files using the find and ffmpeg functions and suppressing output questions:
find /mymediapath (\ -name '*.mp4' \) -exec bash -c 'ffmpeg -y -i "$0" -strict -2 "${0/mp4/flv}"' {} \;

Resources