Batch Converting a Directory Tree of Videos Recursively with Handbrake for Streaming to an Xbox360
I've got many many gigs of 640x480 video of the kids and family taken on my Flip Ultra and then HiDef video taken with a Creative Vado HD, my current favorite pocket video camera. There's also a bunch of random videos taken with whatever video-capable digital camera I might have had with me at the moment.
These are fantastic video cameras (especially the Vado) but unfortunately the output they produce aren't easily streamed to any Game Console like a PS3 or Xbox360.
There's a glorious open-source multi-platform video transcoder out there called HandBrake. There's also the more sophisticated Expression Encoder. I usually use these applications (both can be called from the command-line) when I need to encode videos.
I figured I'd just drag the whole folder over and magically these apps would happily encode these hundreds of files and all subdirectories. Both apps are fantastic for doing one file at a time, but when you want to do a thousand, things break down. I googled with Bing for a while then decided that the batch files and MacGyver solutions I was finding were silly. Why not make my own ridiculous solution that at least worked for me?
Even better, why not do it as a one line PowerShell script and see if it's useful to you, Dear Reader? Even better, perhaps you'll re-write it in the comments and one day it won't suck as deeply as it does now.
Regardless, this script is currently, happily chewing away at all my videos and even better, these versions are streamable to my Xbox360 from my Windows Home Server. Woot. The Wife is happy.
Here it is:
gci . *.avi -R | foreach-object { $newfile = $_.Path + $_.DirectoryName + "\" + $_.BaseName + "-convert" + $_.Extension; &"C:\Program Files (x86)\HandBrake\HandBrakeCLI.exe" -i "$_.FullName" -o "$newfile" --preset "Xbox 360" }
Eek! But what price my immortal soul?
You need PowerShell for this, if you don't already have it. If you have Windows 7, it's already installed!
This poorly written script takes every *.avi file in the current (.) folder, and all folders underneath it (-R), and for each of this files, creates a new filename with the word "-convert" inside. It then calls the HandBrake command line (yours may be in "C:\Program Files" so you might need to change that. It uses the Xbox360 preset.
After this runs, you'll end up with a whole pile of foo-convert.avi files that should/will stream from your machine to your Xbox360 if you are using the free Windows Media Sharing Services. You can also change that profile and convert all your phone for your phone, or whatever you like.
Here's a snapshot of a classic baby video shown on the big screen. Don't you want to come over for dinner now? You can watch slideshows of all our still videos and now hours of family movies. Woot! Works For Me.
PowerShell experts? I'm quite rusty, and I was just interested in the "Getterdone" version. How can we make it better? How about making it so it only updates files that haven't already been encoded?
About Scott
Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.
About Newsletter
I think Windows 7 does it too -http://www.istartedsomething.com/20081115/windows-7-new-decoders-encoders-transcoding/
(PS: I don't think you mean "Windows Media Streaming Services", which is a enterprise media server thing)
Nearly choked on my sandwich when I read this. Good one!
Handbrake is the bomb, but I hate it when you spend literally 2 or 3 days encoding a hi-def video only to find accidentally messed up a parameter and the resultant video isn't compatible with your media setup (PS3 in my case). Also, the UI is bug-ridden and can cause no end of pain when you think you're encoding with one set of parameters only to find those parameters weren't correctly passed onto the command line.
The reason I still occasionally need to use handbrake (rather than transcoding on the fly) is to reduce file sizes. I just can't justify using upwards of 10GB for a single movie, so I use handbrake to get it down to a much more reasonable size, without too much loss of quality.
I never had any luck with TVersity. Seemed good in theory, but in practice it was way too instable and buggy for me.
I did think something like this (not tested)
gci . *.avi -R |
where {$_.basename -notmatch 'convert'} |
foreach {
&"C:\Program Files (x86)\HandBrake\HandBrakeCLI.exe" -i $_.FullName -o "$($_.DirectoryName)\($_.BaseName)-convert$($_.Extension)" --preset "Xbox 360"
}
Greetings MOW
...in response to "How do I write a batch file that..." some people will say, "First, install <perl|bash|monad|...>". This doesn't actually solve the problem; it merely replaces it with a different problem.
In particular, if the solution begins with "First, install..." you've pretty much lost out of the gate. Solving a five-minute problem by taking a half hour to download and install a program is a net loss.
In the spirit of those words, here is a version that will, in theory, run on every version of Windows without requiring PowerShell or any third-party shell:
@for /f "delims=-. tokens=1-3" %%F in ('dir /b /s *.avi') do @if /i not [%%G] == [convert] (
"C:\Program Files (x86)\HandBrake\HandBrakeCLI.exe" -i "%%F.%%G" -o "%%F-convert.%%G" --preset "Xbox 360"
)
If you were outputting the files to a new directory, you could eliminate the @if condition and use:
@for /r %%F in (*.avi) do @echo "C:\Program Files (x86)\HandBrake\HandBrakeCLI.exe" -i "%%F" -o "C:\OUTPUT%%~pnF-convert%%~xF" --preset "Xbox 360"
Did you see the powershell sample that came with Expression Encoder? It does exactly what you are looking for.
$handbrake = "C:\Program Files (x86)\HandBrake\HandBrakeCLI.exe"
$files = @(Get-ChildItem . *.avi -Recurse | Where {$_ -notmatch '-convert\.avi$'})
foreach ($file in $files) {
$newFileName = $file.Fullname -replace '\.avi$','-convert.avi'
& $handbrake -i $file.FullName -o $newFileName --preset "Xbox 360"
if ($LastExitCode -ne 0) { Write-Warning "Error converting $($file.FullName)" }
}
Note: I'm not sure handbrakeCLI returns a non-zero exit code to indicate an error but if it does, you probably want to know about it.
Is that even possible? I would assume that one can only 'google' (verb) with google (noun).
I don't know what you would do with bing though. 'I bunged with bing...' or maybe just the more boring 'Searched with bing...'
At the very least, if that's not a grammatical mistake, it must surely be a marketing nightmare.
That is the one, along with the Expression powershell module that is in the same folder you can convert an entire folder of videos to the template of your choice.
Either I suppose it works. I preferred Expression to Handbrake because I thought to output of the expression encoder was better and I had issue with handbrake crashing on my Win7 x64 machine.
As mentioned above, the reason why XBMC is so popular is it can handle almost anything (and from anywhere) if the 360 could sit under my TV and do the same it would be great.
Open *admin* cmd prompt or powershell
cd "C:\Program Files (x86)\Microsoft Expression\Encoder 3\SDK\samples\EncoderPowerShellModule"
msbuild
close and open a new powershell. To encode a folder full of videos to H.264 for the new Zune HD
Import-Module ExpressionEncoder
gci 'C:\users\Public\Videos\Sample Videos' | Convert-Media -H264ZuneHDAVDockPlayback -Output $home\desktop
More sample scripts listed in here:
C:\Program Files (x86)\Microsoft Expression\Encoder 3\SDK\Doc\Microsoft.Expression.Encoder.chm
$handbrake = "C:\Program Files (x86)\HandBrake\HandBrakeCLI.exe"
$files = @(Get-ChildItem . *.avi -Recurse | Where {$_ -notmatch '-convert\.avi$'})
foreach ($file in $files)
{
$newFileName = $file.Fullname -replace '\.avi$','-convert.avi'
if(![System.IO.File]::Exist($newFileName))
{
& $handbrake -i $file.FullName -o $newFileName --preset "Xbox 360"
if ($LastExitCode -ne 0)
{
Write-Warning "Error converting $($file.FullName)"
}
}
else
{
write-Warning "File $($file.FullName) Previously Converted"
}
}
Sorry about the formatting...
So, finally my question: can PowerShell tell that the file is still being copied to the directory (the file is incomplete), and ignore it?
Thank you for posting scripts in various languages. Scriptability is better compared to manually handling each file, one at a time.
I am currently in need of biterscripting scripts for handling media files. There are some scripts at http://www.biterscripting.com/helppages_samplescripts.html but noone handle media files.
Can you post some biterscripts when you get a chance ? Will be very useful. Thanks.
Comments are closed.