Save this script somewhere, e.g. /usr/local/bin/podit, then chmod 755 /usr/local/bin/podit
Usage: podit /path/to/file
Update: Apparently ffmpeg's parameters have changed yet again [sigh]. Depending on what version of ffmpeg you are using, you may need to make the following changes:
Update 1:
-vcodec h264 is now "-vcodec libx264"
-acodec aac is now "-acodec libfaac"
Update 2:
-me is now "-me_method"
-loop is now "-flags +loop"
-slice is now "-flags +slice"
(To set both the above, use "-flags +loop+slice"
-part[xxx] is now "-partitions +parti4x4+partp8x8+partb8x8"
-brdo has gone. This is automatically set if "-subq" is 7 or higher
-chroma is now "-cmp +chroma"
Also ... nobody noticed that "aspect_ratio=xxx" was missing from the variables section (as it stood, this script would not have worked, but just produce an error "invalid aspect ratio")? Oh well, it's fixed now :)
Thanks to FakeOutdoorsman for update 1, and various sources for update 2.
#!/bin/bash # Name: podit # Summary: iPod H264 640x480 video transcoder script # Version: 1.1.4 # Date: 2009.10.12 # License: GPLv3+ # URL: http://slated.org/howto_transcode_h264_for_ipod_with_ffmpeg # © Homer, 2007 - 2009 # # Requires: ffmpeg # Requires: gpac # Requires: perl-DateManip # These requirements are a guide only. As a minimum you'll # need ffmpeg and MP4Box (from gpac). You could even get away # without using MP4Box, although I doubt you will have iTunes # compatible files (they'll still work with the iPod though). # Any components you don't want to use (MP4Box, Perl-DateManip) # will need to be edited/commented out of this script first. ######################################################################### # This program is free software: you can redistribute it and/or modify # # it under the terms of the GNU General Public License as published by # # the Free Software Foundation, either version 3 of the License, or # # (at your option) any later version. # # # # This program is distributed in the hope that it will be useful, # # but WITHOUT ANY WARRANTY; without even the implied warranty of # # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # # GNU General Public License for more details. # # # # You should have received a copy of the GNU General Public License # # along with this program. If not, see <http://www.gnu.org/licenses/>. # ######################################################################### ########################################################### # Credits... # # Forums: Doom9, Videohelp, and Ubuntu. # # Mailing lists: MPlayer and ffmpeg. # # Blogs: Everywhere. # # # # Special thanks to jdong on Ubuntu forums. # # # # Note 1: This script is *very* CPU intensive (slow), # # and will probably melt your PC, but then again # # it *does* produce incredibly high quality video # # so IMHO it's worth it. YMMV. # # # # Note 2: Now uses MP4Box to "fix" the files for iTunes. # # # # Note 3: I've changed podit to work on a *copy* of the # # original file, rather than directly on the # # source, primarily because I was transcoding # # over a network, and it just made more sense to # # work on local copies. # # # ########################################################### ################################ ### User definable variables ### ########################################################### # These are the only 4 prefs I would recommend you alter. # ########################################################### # # # framerate: e.g. (10, 15, 23.976, 25, 29.97, 30 = MAX) # # A value of 0 will make the output file the same frame # # -rate as the input file. # # # # framelimit: transcode only the first [n] frames. # # (Good for testing.) A value of 0 disables this limit. # # # # resolution: 320x240 / 640x480 (4:3 aspect) # # 320x176 / 640x352 (16:9 aspect) # # Other resolutions are possible (untested). # # # # passes: 1 or 2 pass encoding. ffmpeg does not support # # >2 passes, not that >2 passes is very useful anyway. # # # # NOTE: THIS SCRIPT CURRENTLY DOES *NO* ERROR CHECKING, # # SO PLEASE USE SENSIBLE VALUES. # # # ########################################################### framerate=25 framelimit=1000 resolution="640x480" passes=2 croptop_val=0 cropbottom_val=0 cropleft_val=0 cropright_val=0 video_bitrate="600k" audio_bitrate="160k" aspect_ratio="4:3" ######################## ### Static variables ### ######################## infile="$1" tmpdir="${HOME}/tmp" ############################ ### transcoding function ### ############################ podenc () { local passval=$1 if [ $passval -eq 0 ] then local passvar="" else local passvar="-pass $passval" fi if [ $passval -eq 1 ] then local audiovar="-an" local outvar="/dev/null" else local audiovar="-acodec libfaac -ab $audio_bitrate -ar 48000 -ac 2" local outvar="$tmpfile2" fi if [ $framelimit -eq 0 ] then local framesvar="" else local framesvar="-vframes $framelimit" fi if [ $framerate -eq 0 ] then local ratevar="" else local ratevar="-r $framerate" fi ### You are not expected to understand this. I know *I* don't. nice -n 19 ffmpeg -y $ratevar -i "$tmpfile1" $ratevar $framesvar \ -cropleft $cropleft_val -cropright $cropright_val \ -croptop $croptop_val -cropbottom $cropbottom_val \ -v 1 -vcodec libx264 -b $video_bitrate -bt 175k -refs 2 \ -deblockalpha 0 -deblockbeta 0 -flags +loop+slice \ -partitions +parti4x4+partp8x8+partb8x8 \ -me_method 8 -me_range 21 -subq 7 -cmp +chroma \ -bf 0 -level 13 -g 300 -keyint_min 30 -aspect $aspect_ratio \ -sc_threshold 40 -rc_eq 'blurCplx^(1-qComp)' -qcomp 0.7 \ -qmax 35 -qdiff 4 -i_qfactor 0.71428572 -b_qfactor 0.76923078 \ -maxrate 768k -bufsize 3000k -s $resolution -f mp4 \ $audiovar $passvar "$outvar" exit_status=$? } ######################################## ###### Calculate transcoding time ###### ######################################## transtime () { local newdate=$1 local olddate=$2 local difftime=$(echo "${olddate} ${newdate}" | \ awk '{print "perl -MDate::Manip -e '\''$delta = DateCalc(""\""$1"\""",""\""$2"\""",\\$err,1); print $delta;'\''"}' | \ sh | sed -e s/^.//) local diffyears=$(echo $difftime | cut -d':' -f1) local diffmonths=$(echo $difftime | cut -d':' -f2) local diffweeks=$(echo $difftime | cut -d':' -f3) local diffdays=$(echo $difftime | cut -d':' -f4) local diffhours=$(echo $difftime | cut -d':' -f5) local diffminutes=$(echo $difftime | cut -d':' -f6) local diffseconds=$(echo $difftime | cut -d':' -f7) echo -ne "\033[1;31mTranscoding time: " if [ "$diffyears" -ne 0 ] then echo -n "$diffyears Years, " fi if [ "$diffmonths" -ne 0 ] then echo -n "$diffmonths Months, " fi if [ "$diffweeks" -ne 0 ] then echo -n "$diffweeks Weeks, " fi if [ "$diffdays" -ne 0 ] then echo -n "$diffdays Days, " fi if [ "$diffhours" -ne 0 ] then echo -n "$diffhours Hours, " fi if [ "$diffminutes" -ne 0 ] then echo -n "$diffminutes Minutes, " fi echo -e "$diffseconds seconds.\033[0m" } ############################## ###### Reverse a string ###### ############################## reverseit () { local instring=$1 instring_length=$(echo -n "$instring" | wc -c) reverse_string= while [ $instring_length -gt 0 ] do reverse_string=${reverse_string}$(echo $instring | cut -c $instring_length) let instring_length=instring_length-1 done echo "$reverse_string" } ################################## ###### Strip file extension ###### ################################## stripext () { local instring=$1 local revnoext_string=$(reverseit "$instring" | sed 's/^.*\.//') reverseit "$revnoext_string" } ################## ###### Main ###### ################## outdir=$(find "$infile" -printf "%h") base_name=$(basename "$infile") barename=$(stripext "$base_name") outfile="${outdir}/${barename}.podit.mp4" tmpfile1="${tmpdir}/${base_name}" tmpfile2="${tmpdir}/${barename}.podit.mp4" tmpfile3="${tmpdir}/${barename}.podit.m4v" clear mkdir -p "$tmpdir" if [ -e "$outfile" ] then echo -n "\"${outfile}\" already exists. Overwrite? (y/n): " read answer if [ "$answer" != "y" ] then echo "Transcoding aborted on user request." exit 1 else echo fi fi count=1 while [ $count -lt 11 ] do let countdown=11-$count let count=count+1 echo -n "Transcode will proceed in $countdown seconds." sleep 1 echo -ne "\b \b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b" done echo -ne " \b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b" rm -f "$tmpfile1" "$tmpfile2" "$tmpfile3" "$outfile" echo "Copying \"${base_name}\" to \"${tmpdir}\"" rsync -v --progress "$infile" "$tmpfile1" starttime=$(date +%Y%m%d%H:%M:%S) echo if [ "$passes" -eq 1 ] then podenc 0 else podenc 1 podenc 2 fi if [ "$exit_status" -ne 0 ] then echo "Something went wrong with ffmpeg." echo "Please check the output and try again." exit 1 fi endtime=$(date +%Y%m%d%H:%M:%S) echo transtime $starttime $endtime echo echo "Removing temporary copy of source file." rm -f "$tmpfile1" echo echo "Fixing transcoded file for iPod with MP4Box." echo MP4Box -ipod -add "$tmpfile2" "$tmpfile3" if [ "$?" -ne 0 ] then echo "Something went wrong with MP4Box." echo "Please check the output and try again." exit 1 fi echo echo "Removing MP4Box's temporary source file." rm -f "$tmpfile2" echo echo "Moving finished video to $outdir" mv "$tmpfile3" "$outfile" echo echo -e "\033[1;31mJob \"${barename}\" completed successfully.\033[0m" exit 0
Attachment | Size |
---|---|
podit-1.1.4.tar.bz2 | 4.13 KB |
Comments
Script problem
Hi
I keep on getting this:
"Unknown encoder libx264" even when I edit in the full path (/usr/lib64...)
Can't figure out what's happening. (Running Ubuntu LTS 10.4 64 bits)
(Re)install x264
You either don't have x264 installed, or you have the wrong version (presumably from the Medibuntu repos), so need to uninstall the old version then install the latest one.
http://ubuntu-ky.ubuntuforums.org/showthread.php?t=1117283
Error when using latest ffmpeg (SVN r19736)
I get the following error when testing the script on a video with the latest ffmpeg. I'm guessing it has something do with commandline options changing, but I'm not very experienced with ffmpeg. Does anyone have any suggestions? Output is below.
Thanks!
----------------------
FFmpeg version SVN-r19736, Copyright (c) 2000-2009 Fabrice Bellard, et al.
configuration: --enable-gpl --enable-nonfree --enable-pthreads --enable-libfaac --enable-libfaad --enable-libmp3lame --enable-libtheora --enable-libx264 --enable-libxvid --enable-x11grab
libavutil 50. 3. 0 / 50. 3. 0
libavcodec 52.34. 0 / 52.34. 0
libavformat 52.38. 0 / 52.38. 0
libavdevice 52. 2. 0 / 52. 2. 0
libswscale 0. 7. 1 / 0. 7. 1
built on Aug 27 2009 22:38:35, gcc: 4.3.3
Seems stream 0 codec frame rate differs from container frame rate: 47.95 (1918/40) -> 23.98 (24000/1001)
Input #0, matroska, from '/home/dwoods/tmp/Gorillaz - Feel Good.mkv':
Duration: 00:04:06.71, start: 0.000000, bitrate: N/A
Stream #0.0: Video: h264, yuv420p, 1280x720, PAR 1:1 DAR 16:9, 23.98 tbr, 1k tbn, 47.95 tbc
Stream #0.1: Audio: vorbis, 44100 Hz, 2 channels, s16
Invalid value '1' for option 'loop'
FFmpeg version SVN-r19736, Copyright (c) 2000-2009 Fabrice Bellard, et al.
configuration: --enable-gpl --enable-nonfree --enable-pthreads --enable-libfaac --enable-libfaad --enable-libmp3lame --enable-libtheora --enable-libx264 --enable-libxvid --enable-x11grab
libavutil 50. 3. 0 / 50. 3. 0
libavcodec 52.34. 0 / 52.34. 0
libavformat 52.38. 0 / 52.38. 0
libavdevice 52. 2. 0 / 52. 2. 0
libswscale 0. 7. 1 / 0. 7. 1
built on Aug 27 2009 22:38:35, gcc: 4.3.3
Seems stream 0 codec frame rate differs from container frame rate: 47.95 (1918/40) -> 23.98 (24000/1001)
Input #0, matroska, from '/home/dwoods/tmp/Gorillaz - Feel Good.mkv':
Duration: 00:04:06.71, start: 0.000000, bitrate: N/A
Stream #0.0: Video: h264, yuv420p, 1280x720, PAR 1:1 DAR 16:9, 23.98 tbr, 1k tbn, 47.95 tbc
Stream #0.1: Audio: vorbis, 44100 Hz, 2 channels, s16
Invalid value '1' for option 'loop'
Something went wrong with ffmpeg.
Please check the output and try again.
ffmpeg devs have changed things once again...
Invalid value '1' for option 'loop'
IOW the loop option has changed. I have no idea what value it expects, nor where the necessary documentation for the changes is.
Some quick research would seem to indicate the "-me" option has gone too.
Try removing both of those switches in the ffmpeg command, and see if it works.
I haven't updated ffmpeg in a long time, and indeed I try to avoid doing so, for exactly these reasons.
OK, it's all fixed now ... again
I've updated the script to reflect yet more changes to ffmpeg (see above).
Error "let: not found" ?
I've loving the idea of this script. Looks like it'll do everything I want it to, except that it doesn't.
Trying this on Ubuntu 8.04, I can't seem to get past an error of "/usr/local/bin/podit: 238: let: not found" and while I'm always up to learning and messing around, I can't quite seem to get over this stumbling block. Anything you can suggest?
Ubuntu uses the wrong shell
Apparently the default shell in Ubuntu is "dash", which does not support bash builtins like "let" for some reason.
Simply change the first line of the script to:
#!/bin/bash
And make sure bash is installed.
See also: http://ubuntuforums.org/showpost.php?p=2474419&postcount=10
Works like a charm!
The shell change makes everything happy. Many thanks for the prompt reply, and this wonderful script!
Where is deltadays.pl?
More information, please!
deltadays.pl is in the above post
Please read the last few lines of the post starting with: "Save the following as /usr/local/bin/deltadays.pl then chmod 755 /usr/local/bin/detadays.pl".
HTH.
should detadays.pl be deltadays.pl?
Probably explains one of the comments
Thanks for the heads-up
Typo corrected.
Works but the output file...
Hello,
Awesome script. It works well and the product is high quality. However I am having one little issue.
The script runs and it copies the original source file to the tmp folder but the file it creates is called something like 1\n0\n11.podit.m4v (\n = newline) and then after the file is done encoding it can't move it back to the original sources folder.
I'm running FreeBSD 6.3, everything up to date. I'll probably be able to figure it out but just a heads up.
Weird characters in source filename
Can you post the exact name (including path) of the source file?
This script does almost no error checking, and makes no allowances for weird filenames, so the best I can advise is that you make sure all your sources have names with legal chars before proceeding.
I may look into a better way of dealing with this in the future.
I am working on an update, which at this stage is merely feature enhancements (autocrop and other goodies), but I suppose I will get around to doing more extensive error checking too.
Great Script!
Great Script! Thanks been browsing around the tubes for a while and this is the best solution out there. Thanks for sharing!
File Name extension removal in script
Very nice script. I did make one change though:
The stripext() function did not seem to work well for me. If a file name had more than one dot, it would grab the first part of the filename.
"this.file.mp4" became "this.mp4"
I did the following to correct this, making the stripext() and reversit() functions not necessary:
##################
###### Main ######
##################
outdir=$(find "$infile" -printf "%h")
base_name=$(basename "$infile")
barename=$(basename "$infile" | sed 's/\(.*\)\..*/\1/')
#barename=$(stripext "$base_name")
Yeah it works like a charm.
This Script has solved alot of my problems. I spent alot of time doing things the manual way up until now.
Great job.
Thanks for this script.
NssY.