How do I programmatically convert FLV video files to MP4 using a shell script in OS X?
You can install ffmpeg via Homebrew or MacPorts. The commnd to install ffmpeg with Homebrew is brew install ffmpeg
; similarly, the command to install ffmpeg with MacPorts is sudo port install ffmpeg
. Once you've installed ffmpeg, here is a simple (and somewhat naive) script for converting the files. You may need to add more flags, depending on your desired options.
#! /bin/bash
function convert_all_to_mp4() {
for file in *.flv ; do
local bname=$(basename "$file" .flv)
local mp4name="$bname.mp4"
ffmpeg -i "$file" "$mp4name"
done
}
convert_all_to_mp4
Just make whatever file you put the script above in executable (for example, chmod a+x path/to/convert_all_to_mp4.sh
) and invoke it by its fully qualified path or add the directory containing it to the PATH environment varaible and invoke the script by the name you gave it.
Conversion from FLV to MP4 using ffmpeg
Aim: Convert multiple Adobe Flash Video (FLV) files to MP4 using a Bash script.
My Environment: MAC OS X 10.5.8, Terminal v.240.2, Bash v.3.2.17 (This solution should work with most Apple Mac systems).
Language: bash
Description: This script will search for all FLV files in the specified location, iterate through each one, converting them to an equivalent MP4 video and place them in the sub-directory MP4-yymmdd-HHMMSS. Log files generated during the process are placed in the log directory within this sub-directory.
Prerequisites:
Download the ffmpeg binary and place in the /usr/local/bin
directory.
My code is based on Jan's blog on trick77.com. See "References" for details.
Download my bash script from the "Bash Script" section.
Explanation of my code
- Copy any MP4 files present
- Detect the video codec type using
ffmpeg -i [file]
. - Cycle through each video and convert according to the type of video codec used.
- Concatenate all the ffmpeg log files
Only processes videos with the FLV1 and H264 codecs.
Usage:
convert-flv-to-mp4.sh [folder path]
Example:
./convert-flv-to-mp4.sh /Users/Shared/Music
Output:
mp4 files in the MP4-yymmdd-HHMMSS subdirectory
Logs:
convert-flv-to-mp4.log.txt - program log
ffmpeg-yyyymmdd-HHMMSS.log.txt - ffmpeg binary log for each file converted
ffmpeg.log.txt - compilation of all the above ffmpeg logs
metadata.csv - metadata for each video file
Discussion:
In my first attempt, I was not able to convert videos with the FLV1 video stream using the -copy
ffmpeg option. Instead, I needed to use the following ffmpeg options:
-strict experimental -b:a 64k
This means that the conversion doesn't halt on minor errors and that it uses 64k audio bit rate conversion.
Using the -copy
option just remuxes the input video and hence is fast. Otherwise, ffmpeg will transcode the file, which takes considerably longer. This script will determine which option to use.
Key snippet of code:
ls ${inputdir}/*.flv>$inputlist
for i in $(cat $inputlist); do
...
case $vtype in
flv1)
ffmpeg -report -v info -nostdin -fflags discardcorrupt -i $i -strict experimental -c:v mpeg4 -b:a 64k ${outputdir}/${basename}.mp4
h264)
ffmpeg -report -v verbose -nostdin -fflags discardcorrupt -i $i -vcodec copy -acodec copy ${outputdir}/${basename}.mp4
esac
...
done
where:
inputlist - file containing all the FLV files
vtype - the video codec type of the input file
i - the input FLV filename
Example log file:
Metadata log file:
Conclusion:
A complete solution was successfully tested on 73 FLV files downloaded from youtube. It took 8 minutes to transcode 34 files and remux 39 files, on average 11MB in size.
Bash Script:
convert-flv-to-mp4.sh
References:
FFmpeg Binary Download
FFmpeg Official Documentation
How to convert .flv Flash video to .mp4 on the Mac
Extensibility:
If you have any FLV files that have a video stream other than FLV1 or H264, e.g. VP6, FLV4, add a comment with a link to your video file and I will update my code to handle it.
#!/bin/bash
shopt -s nullglob
shopt -s nocaseglob
for file in *.flv
do
ffmpeg -i "$file" "${file%flv}mp4"
done