Monday, March 22, 2010

Ripping and Transcoding Movies

I use MakeMKV to rip DVDs and Blu Rays to an archive format. I typically rip the main video title, the primary audio track, and all subtitles. I rip the videos to \\SERVER\Videos\Incoming, which is a share residing on my Windows Home Server. I have the script below running as a service (using SrvAny.exe and Any Service Installer), although running it as a service is totally optional. The script below watches that Incoming folder and when it finds a new file, it verifies that it's not still being written (that its size doesn't change in 5 seconds), and then it kicks off two transcode jobs using HandBrake, one for an iPhone and one for an archive format.

Once you get this job set up, all you have to do is rip your movie into \\SERVER\Videos\Incoming\[MOVIE NAME]\title00.mkv and the transcodes will be dumped into \\SERVER\Videos\Movies\[MOVIE NAME]\iPhone.m4v and Archive.mp4. In other words, one-click transcoding.

Write-Output ("Setting process priority to Idle."); [System.Diagnostics.Process]::GetCurrentProcess().PriorityClass = [System.Diagnostics.ProcessPriorityClass]::Idle; $incomingDir = "\\SERVER\Videos\incoming"; # Loop forever while(1) { $mkvs = get-childitem $incomingDir -recurse -filter *.mkv; if(!($mkvs)) { Write-Output ("No file found."); } else { # Force into an array if only one element found if(!($mkvs.Count)) { $mkvs = ,$mkvs; } Write-Output ("Found $($mkvs.Count) files"); foreach($mkv in $mkvs) { Write-Output ("Processing $($mkv.Directory.Name)"); #if($mkv.Directory.Name -notmatch "There Will Be Blood") #{ # continue; #} Write-Output ("Checking to see if file is still being written..."); $info1 = Get-Item $mkv.FullName; start-sleep 5; $info2 = Get-Item $mkv.FullName; Write-Output ("."); if($info1.Length -ne $info2.Length) { Write-Output ("Skipping!"); continue; } $outputDir = "\\SERVER\Videos\movies\$($mkv.Directory.Name)"; $outputFilePrefix = "\\SERVER\Videos\movies\$($mkv.Directory.Name)\$($mkv.Directory.Name)"; if(!(test-path $outputDir)) { mkdir $outputDir; } # Kick off two transcode jobs $psI = [Diagnostics.Process]::Start("C:\Program Files\Handbrake\HandBrakeCLI.exe", "-i ""$($mkv.FullName)"" -t 1 -o ""$outputFilePrefix - iPhone.m4v"" -f mp4 -X 480 -e x264 -q 20 -a 1 -E faac -6 dpl2 -R 48 -B 128 -D 0.0 --markers=""C:\Documents and Settings\Administrator\Local Settings\Temp\2\iPhone-1-chapters.csv"" -x cabac=0:ref=2:me=umh:bframes=0:subq=6:8x8dct=0:trellis=0:weightb=0 -v 1"); #2>"$outputFilePrefix - iPhone - Error.txt" > "$outputFilePrefix - iPhone.txt"; $psA = [Diagnostics.Process]::Start("C:\Program Files\Handbrake\HandBrakeCLI.exe", "-i ""$($mkv.FullName)"" -t 1 -o ""$outputFilePrefix - Archive.mkv"" -f mkv --strict-anamorphic -e x264 -q 20 -a 1 -E ac3 -6 auto -R Auto -B 32 -D 0 --markers=""C:\Documents and Settings\Administrator\Local Settings\Temp\2\archive-1-chapters.csv"" -x ref=2:bframes=2:subq=6:mixed-refs=0:weightb=0:8x8dct=0:trellis=0 -v"); #$psI = & "C:\Program Files\Handbrake\HandBrakeCLI.exe" -i "$($mkv.FullName)" -t 1 -o "$outputFilePrefix - iPhone.m4v" -f mp4 -X 480 -e x264 -q 20 -a 1 -E faac -6 dpl2 -R 48 -B 128 -D 0.0 --markers="C:\Documents and Settings\Administrator\Local Settings\Temp\2\iPhone-1-chapters.csv" -x cabac=0:ref=2:me=umh:bframes=0:subq=6:8x8dct=0:trellis=0:weightb=0 -v 1 2>"$outputFilePrefix - iPhone - Error.txt" > "$outputFilePrefix - iPhone.txt" #$psA = & "C:\Program Files\Handbrake\HandBrakeCLI.exe" -i "$($mkv.FullName)" -t 1 -o "$outputFilePrefix - Archive.mkv" -f mkv --strict-anamorphic -e x264 -q 20 -a 1 -E ac3 -6 auto -R Auto -B 32 -D 0 --markers="C:\Documents and Settings\Administrator\Local Settings\Temp\2\archive-1-chapters.csv" -x ref=2:bframes=2:subq=6:mixed-refs=0:weightb=0:8x8dct=0:trellis=0 -v 2>&1 #> "$outputFilePrefix - Archive.txt" $psI.WaitForExit(); $psA.WaitForExit(); mv $mkv.FullName "$outputFilePrefix - Original.mkv"; if($psI) { #echo "in it"; #$psI.WaitForExit(); #Wait-Process -InputObject $psI; #Wait-Process -InputObject $psA; #mv $mkv.FullName "$outputFilePrefix - Original.mkv"; } else { #Write-Output ("Error processing $($mkv.Directory.Name)"); } #break; } } # Wait one minute, and then try again. start-sleep 60; }

Thursday, March 11, 2010

How to access the Targeting Context from within a Commerce Server Basket Pipeline

I fixed a bug yesterday where an order-level discount targeted against Targeting Context.Subtotal had an incorrect value—it was set in code before running the basket pipeline, but the subtotal was inaccurate before running the pipeline (newly added items to the basket had a price of zero prior to the pipeline execution, for example).

The solution was to update the subtotal in the targeting context during pipeline execution, after fetching the latest pricing data from the catalog and before running the OrderDiscount pipeline component. Here’s the code to get at the targeting context from within a pipeline:

public int Execute(object pdispOrder, object pdispContext, int lFlags)
{
    IDictionary context = (IDictionary)pdispContext;
    Decimal subtotal = (decimal)((Microsoft.CommerceServer.Interop.Profiles.IProfileObject)context["ContextProfile"]).Fields["Subtotal"].Value;
}