View Single Post
Old 10th May 2009, 10:39   #1  |  Link
sportsracer
Registered User
 
Join Date: Apr 2009
Posts: 1
Script for x264/AAC/MP4 batch encoding

I wrote this Powershell script to encode hundreds of AVI clips from my camera and thought it may be of use to someone.

An AVS script is generated for every AVI that is found in the folder given as a command line argument. You need to configure exe paths and command line options for x264, neroaacenc etc. before using the script.

If you haven't used Powershell before, you can download it from Microsoft for free, then type in "Set-ExecutionPolicy Unrestricted" 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 ".\filename.ps1 D:\Folder_of_AVIs".

Code:
# Description: Batch encoding from AVI file to x264/AAC in MP4 file.
# Example Usage: .\VidBatch.ps1 "D:\Folder_of_AVIs"
# Required tools: x264, bepipe, neroaacenc, mp4box, AviSynth - be sure to adapt exe paths below

Param (
	[string]$Path
) 

# Configure paths here. Temporary files (AVS, video, audio) are saved in $TempPath which is cleared out after every file. Muxed video is saved to $OutPath

$TempPath	= 'D:\Temp\'
$OutPath	= 'D:\Output\'

# Configure exe paths here.

$ExePath = @{}
$ExePath['x264']	= $env:programfiles + '\megui\tools\x264\x264.exe'
$ExePath['bepipe']	= $Home + '\Downloads\BePipe.exe'
$ExePath['neroaacenc']	= $env:programfiles + '\megui\neroAacEnc.exe'
$ExePath['mp4box']	= $env:programfiles + '\megui\tools\mp4box\MP4Box.exe'

# Configure AVS script and command line parameters here

$Config = @{}
$Config['AVS'] = 'DirectShowSource("$FilenameIn")'
$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['neroaacenc'] = '-br 64000 -if - -of "$FilenameAudio"'

function StartProcess($Filename, $Arguments) {

	$ProcessInfo = New-Object System.Diagnostics.ProcessStartInfo
	$ProcessInfo.FileName = $Filename
	$ProcessInfo.Arguments = $Arguments
	$ProcessInfo.UseShellExecute = $False
	[System.Diagnostics.Process]::Start($ProcessInfo).WaitForExit()
}

function PipeProcesses($Filename1, $Arguments1, $Filename2, $Arguments2) {

	$ProcessInfo1 = New-Object System.Diagnostics.ProcessStartInfo
	$ProcessInfo1.FileName = $Filename1
	$ProcessInfo1.Arguments = $Arguments1
	$ProcessInfo1.UseShellExecute = $False
	$ProcessInfo1.RedirectStandardOutput = $True
	$Process1 = [System.Diagnostics.Process]::Start($ProcessInfo1)

	$ProcessInfo2 = New-Object System.Diagnostics.ProcessStartInfo
	$ProcessInfo2.FileName = $Filename2
	$ProcessInfo2.Arguments = $Arguments2
	$ProcessInfo2.UseShellExecute = $False
	$ProcessInfo2.RedirectStandardInput = $True
	$Process2 = [System.Diagnostics.Process]::Start($ProcessInfo2)

	$Process2.StandardInput.Write($Process1.StandardOutput.ReadToEnd())
	
	$Process2.WaitForExit()
}

function Encode($FilenameIn) {

	Write-Host "Encoding $FilenameIn"

	$Basename = [system.io.path]::GetFilenameWithoutExtension($FilenameIn)
	$FilenameAVS = $TempPath + $Basename + '.avs'
	$FilenameVideo = $TempPath + $Basename + '_video.mp4'
	$FilenameAudio = $TempPath + $Basename + '_audio.mp4'
	$FilenameOut = $OutPath + $Basename + '.mp4'

	Write-Host '- Generating AVS script...'
	$Config['AVS'].Replace('$FilenameIn', $FilenameIn) | Out-File $FilenameAVS -Encoding 'ASCII'
	
	Write-Host '- Encoding video...'
	StartProcess $ExePath['x264'] $Config['x264'].Replace('$FilenameVideo', $FilenameVideo).Replace('$FilenameAVS', $FilenameAVS)
	
	'- Encoding audio...'
	PipeProcesses $ExePath['bepipe'] ('--script "Import(^' + $FilenameAVS + '^)"') $ExePath['neroaacenc'] $Config['neroaacenc'].Replace('$FilenameAudio', $FilenameAudio)
	
	Write-Host '- Muxing...'
	StartProcess $ExePath['mp4box'] ('-new -add "' + $FilenameVideo + '" -add "' + $FilenameAudio + '" "' + $FilenameOut + '"')
	
	Write-Host '- Cleaning up...'
	Get-ChildItem $TempPath | ForEach-Object { Remove-Item $_.fullname }
	
	Write-Host '- Done'
}

Write-Host 'VidBatch'

$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 -Filter '*.avi' $Path | ForEach-Object { Encode $_.FullName }
} else {
	Write-Host "$Path is not a file/folder"
}
sportsracer is offline   Reply With Quote