Welcome to Doom9's Forum, THE in-place to be for everyone interested in DVD conversion.

Before you start posting please read the forum rules. By posting to this forum you agree to abide by the rules.

 

Go Back   Doom9's Forum > Video Encoding > MPEG-4 AVC / H.264

Reply
 
Thread Tools Search this Thread Display Modes
Old 11th January 2010, 05:30   #1  |  Link
grv575
Registered User
 
Join Date: May 2003
Posts: 25
Batch encoding to h264

Powershell script to batch 2-pass encode files to h264/aac using the same bitrate as the source file.

Required tools -
x264: http://x264.nl/
bepipe: http://speeddemosarchive.com/w/images/e/e3/BePipe.zip
neroaacenc: http://speeddemosarchive.com/w/image...gitalAudio.zip
mp4box: http://www.videohelp.com/tools/mp4box
AviSynth: http://sourceforge.net/projects/avisynth2/files/
avsutil: http://members.optusnet.com.au/squid_80/avsutil.zip

# An AVS script is generated for every AVI that is found in the source folder
# The source video total bitrate is approximated based on the filesize and video runtime. This will give a good value to use as the bitrate for a 2-pass encode to ensure
# little loss of quality during transcoding.
#
# If you haven't used Powershell before, you can download it from Microsoft for free, then type in "Set-ExecutionPolicy RemoteSigned" to allow execution of unsigned scripts.
# Save the code in a .ps1 file, navigate to that folder in Powershell (works just like in cmd.exe) and type in ".\encode.ps1".
# Or you can just open a cmd shell and type: "powershell .\encode.ps1"

# Description: Batch encoding from various file formats to x264/AAC in an MP4 container.
# Example Usage: .\encode.ps1
# Required tools: x264, bepipe, neroaacenc, mp4box, AviSynth, avsutil - be sure to adapt exe paths below

#Param (
#[string]$Path
#)

# Configure paths here.
# Videos to encode are in $Path
# Temporary files (AVS, video, audio) are saved in $TempPath which is cleared out after every file except on exceptions.
# Muxed video is saved to $OutPath
# $FileTypes lists all file types in $Path that will be encoded

$Path = 'C:\video\source\'
$TempPath = 'C:\video\temp\'
$OutPath = 'C:\video\encoded\'
$FileTypes = @("*.avi","*.mpg","*.mpeg","*.wmv","*.rmvb","*.mkv")

# Configure exe paths here.

$ExePath = @{}
$ExePath['x264'] = 'C:\video\bin\x264.exe'
$ExePath['bepipe'] = 'C:\video\bin\BePipe.exe'
$ExePath['neroaacenc'] = 'C:\video\bin\neroAacEnc.exe'
$ExePath['mp4box'] = 'C:\video\bin\MP4Box.exe'
$ExePath['avsutil'] = 'C:\video\bin\avsutil.exe'

# Configure AVS script and command line parameters here

$Config = @{}
$Config['AVS'] = 'DirectShowSource("$FilenameIn", convertfps=true)'
#$Config['x264'] = '--crf 22 --ref 5 --mixed-refs --bframes 3 --b-adapt 2 --b-pyramid --weightb --deblock -1:-1 --trellis 2 --partitions all --8x8dct --me umh ' +
#'--threads auto --thread-input --progress --no-psnr --no-ssim --output "$FilenameVideo" "$FilenameAVS"'
$Config['x264pass1'] = '--pass 1 --bitrate $BitrateKbps --stats "$FilenameStats" --output NUL "$FilenameAVS"'
$Config['x264pass2'] = '--pass 2 --bitrate $BitrateKbps --stats "$FilenameStats" --output "$FilenameVideo" "$FilenameAVS"'
$Config['neroaacenc'] = '-q 0.55 -if - -of "$FilenameAudio"'
$Config['AVSBitrate'] = 'DirectShowSource("$FilenameIn")' + "`r`n" +
'filename = "$FilenameDuration"' + "`r`n" +
'WriteFileStart(filename, "FrameCount/FrameRate")'

function Encode($FilenameIn) {
Trap {
write-error $_.Exception.Message
return
}

Write-Host "Encoding $FilenameIn"

$Basename = [system.io.path]::GetFilenameWithoutExtension($FilenameIn)
$FilenameAVS = $TempPath + $Basename + '.avs'
$FilenameAVSBitrate = $TempPath + $Basename + '_bitrate.avs'
$FilenameVideo = $TempPath + $Basename + '_video.mp4'
$FilenameAudio = $TempPath + $Basename + '_audio.mp4'
$FilenameStats = $TempPath + $Basename + '.stats'
$FilenameDuration = $TempPath + $Basename + '_duration.txt'
$FilenameOut = $OutPath + $Basename + '.mp4'

Write-Host '- Generating AVS scripts...'
$Config['AVS'].Replace('$FilenameIn', $FilenameIn) | Out-File $FilenameAVS -Encoding 'ASCII'
$Config['AVSBitrate'].Replace('$FilenameIn', $FilenameIn).Replace('$FilenameDuration', $FilenameDuration) | Out-File $FilenameAVSBitrate -Encoding 'ASCII'

Write-Host '- Getting bitrate...'
& $ExePath['avsutil'] "$FilenameAVSBitrate"

$FileLengthSeconds = Get-Content "$FilenameDuration"
$file = Get-Item "$FilenameIn"
$FileSize = $file.Length
$BitrateKbps = [int]($FileSize / $FileLengthSeconds * 8 / 1000)
Write-Host "$BitrateKbps kbps"

Write-Host '- Encoding video...'
Write-Host '- Pass 1...'
$Execute = $ExePath['x264'] + ' ' + $Config['x264Pass1'].Replace('$FilenameAVS', $FilenameAVS).Replace('$FilenameStats', $FilenameStats).Replace('$BitrateKbps', $BitrateKbps)
& cmd /c "$Execute"

Write-Host '- Pass 2...'
$Execute = $ExePath['x264'] + ' ' + $Config['x264Pass2'].Replace('$FilenameVideo', $FilenameVideo).Replace('$FilenameAVS', $FilenameAVS).Replace('$FilenameStats', $FilenameStats).Replace('$BitrateKbps', $BitrateKbps)
& cmd /c "$Execute"

'- Encoding audio...'
$Execute = $ExePath['bepipe'] + ' --script "Import(^' + $FilenameAVS + '^)"' + ' | ' + $ExePath['neroaacenc'] + ' ' + $Config['neroaacenc'].Replace('$FilenameAudio', $FilenameAudio)
& cmd /c "$Execute"

Write-Host '- Muxing...'
$Execute = $ExePath['mp4box'] + ' -new -add "' + $FilenameVideo + '" -add "' + $FilenameAudio + '" "' + $FilenameOut + '"'
& cmd /c "$Execute"

Write-Host '- Cleaning up...'
Get-ChildItem $TempPath | ForEach-Object { Remove-Item $_.fullname }

Write-Host '- Done'
}

Write-Host '===Begin Batch Encode==='

$OutPath, $TempPath | ForEach-Object {
if ((Test-Path -PathType 'Container' $_) -eq $False) {
if ((Read-Host "Error: Folder `"$_`" not found, type `"y`" to create it") -eq 'y') {
New-Item $_ -Type Directory | Out-Null
} else {
Write-Host 'Exiting. Edit source file to set up temp and output folders!'
exit
}
}
}

foreach ($Exe in $ExePath.Values) {
if ((Test-Path -PathType 'Leaf' $Exe) -eq $False) {
Write-Host "Error: Executable `"$Exe`" not found."
Write-Host 'Exiting. Edit source file to set up exe paths for x264, bepipe, neroaacenc and mp4box!'
exit
}
}

if ($Path -eq '') {
Write-Host 'Error: No path/file specified'
} elseif (Test-Path -PathType 'Leaf' $Path) {
Encode $Path
} elseif (Test-Path -PathType 'Container' $Path) {
Get-ChildItem ($Path + '*') -Include $FileTypes | ForEach-Object { Encode $_.FullName }
} else {
Write-Host "$Path is not a file/folder"
}

Write-Host '===End Batch Encode==='

Last edited by grv575; 11th January 2010 at 05:32.
grv575 is offline   Reply With Quote
Old 11th January 2010, 07:54   #2  |  Link
stax76
Registered User
 
stax76's Avatar
 
Join Date: Jun 2002
Location: On thin ice
Posts: 6,837
Can it do anything which StaxRip can't do? Why not use a real scripting language like Python or JScript instead of a command shell scripting language? Only benefit PS has for such a script is full COM+ automation and .NET access but other than that it's pretty ugly compared to something elegant like Python.

Last edited by stax76; 11th January 2010 at 08:03.
stax76 is offline   Reply With Quote
Old 11th January 2010, 08:11   #3  |  Link
grv575
Registered User
 
Join Date: May 2003
Posts: 25
Quote:
Originally Posted by stax76 View Post
Can it do anything which StaxRip can't do? Why not use a real scripting language like Python or JScript instead of a command shell scripting language? Only benefit PS has for such a script is full COM+ automation and .NET access but other than that it's pretty ugly compared to something elegant like Python.
I've checked out every single GUI solution and was only happy with WinFF. But ffmpeg has lamemp3 and rmvb bugs and this gets a better encode since it's 2 pass and figures out a good bitrate to use. Basically automating the bitrate & using 2-pass for quality is the reason.

Powershell since it's built into Vista/Win7. I've done plenty of python stuff but really syntax doesn't make that much of a difference.
grv575 is offline   Reply With Quote
Old 11th January 2010, 08:23   #4  |  Link
stax76
Registered User
 
stax76's Avatar
 
Join Date: Jun 2002
Location: On thin ice
Posts: 6,837
The bitrate calculation should be possible with StaxRip, in the x264 dialog you can define custom switches, whenever a switch appears two times the second one is used by x264. There is a Macro to evaluate a JScript expression that can be used to calculate the bitrate. Another thing that might be used is the command line video encoder. 2 pass is typically used to target size restricted mediums, why don't you not simply use '--crf 20'?
stax76 is offline   Reply With Quote
Old 11th January 2010, 08:43   #5  |  Link
grv575
Registered User
 
Join Date: May 2003
Posts: 25
Quote:
Originally Posted by stax76 View Post
The bitrate calculation should be possible with StaxRip, in the x264 dialog you can define custom switches, whenever a switch appears two times the second one is used by x264. There is a Macro to evaluate a JScript expression that can be used to calculate the bitrate. Another thing that might be used is the command line video encoder.
Ah, cool. Looks like you can put together the same thing then. Didn't bother doing any advanced scripting with any of the GUIs beyond avisynth scripts.

Quote:
Originally Posted by stax76 View Post
2 pass is typically used to target size restricted mediums, why don't you not simply use '--crf 20'?
Ongoing discussion:
http://forum.doom9.org/showthread.php?t=151938

Basically because the encodes came out worse.
grv575 is offline   Reply With Quote
Old 11th January 2010, 09:55   #6  |  Link
stax76
Registered User
 
stax76's Avatar
 
Join Date: Jun 2002
Location: On thin ice
Posts: 6,837
StaxRip has also a rich CLI where you can load a template, load file(s) and set the target file size or bitrate etc., the CLI is based on the same command engine the menus use so there are a lot commands available on the CLI. Generally it has rich automation support and allows rich customizations.
stax76 is offline   Reply With Quote
Old 12th January 2010, 10:02   #7  |  Link
creamyhorror
Registered User
 
Join Date: Mar 2008
Posts: 118
Quote:
Originally Posted by grv575 View Post
Ongoing discussion:
http://forum.doom9.org/showthread.php?t=151938

Basically because the encodes came out worse.
To save you guys the trouble of clicking, he basically compared a 2-pass XviD encode to an x264 CRF encode without controlling for audio bitrate. And the XviD turned out better.
creamyhorror is offline   Reply With Quote
Old 12th January 2010, 15:44   #8  |  Link
RunningSkittle
Skittle
 
RunningSkittle's Avatar
 
Join Date: Mar 2008
Posts: 539
Whats the point of this? Your script can be simplified immensely (because it doesnt do anything fancy) to just a few lines in NT Batch...

Code:
*define vars here*
for /r %%a in (*.whatever) do (goto encode "%%a")
goto end
:encode
x264.exe --pass 1 options %1
x264.exe --pass 2 options %1
goto end
:endEncode

:end
RunningSkittle is offline   Reply With Quote
Old 13th January 2010, 05:53   #9  |  Link
grv575
Registered User
 
Join Date: May 2003
Posts: 25
Quote:
Originally Posted by RunningSkittle View Post
Whats the point of this? Your script can be simplified immensely (because it doesnt do anything fancy) to just a few lines in NT Batch...

Code:
*define vars here*
for /r %%a in (*.whatever) do (goto encode "%%a")
goto end
:encode
x264.exe --pass 1 options %1
x264.exe --pass 2 options %1
goto end
:endEncode

:end
Yeah there's a bat one that's similar at:
http://speeddemosarchive.com/kb/Batch_Encoding

It does pretty much the same thing (uses nero AAC codec for the audio), but you specify the bitrate to use.
grv575 is offline   Reply With Quote
Reply

Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT +1. The time now is 13:09.


Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2024, vBulletin Solutions Inc.