This was my first year at Microsoft’s TechEd, and I have to say that I was blown away by the volume of content. There were several different times that I was unable to attend a session that I wanted because I was triple if not quadruple booked.
Now that I’m back at the office, I wanted to pull down the content. I started to do this the old fashioned way, but it was taking forever, I would lose where I was, and I’d get side-tracked by work. So, I did what any sensible person would do, I wrote a PowerShell Script.
The script runs through four stages:
- Gather information from the RSS Feed
- Build up a list of files to download
- Download the files using BitsTransfer (so that it doesn’t hog my machine’s resources)
- Re-tag the Video files with appropriate information (using the TagLib#)
That was fun. Now onto the script…
<# Download-TechEd2013Media.ps1 Downloads the Presentations and Videos from TechEd 2013 North America Site Prerequisites: taglib-sharp.dll in your Working Directory #> #region Cleanup Any Old Runs Get-Variable | Remove-Variable -ErrorAction SilentlyContinue $Error.Clear() Clear-Host Get-BitsTransfer | Remove-BitsTransfer -ErrorAction SilentlyContinue #endregion Cleanup Any Old Runs ############################# # Global Variables ############################## $WorkingDir = "D:WorkingTechEd2013" # Test for the Media Subfolder from the Working Directory # if it's not there, create it if ( -not ( Test-Path ( $WorkingDir + "Media" ) ) { New-Item -Type Directory -Path ( $WorkingDir + "Media" ) | Out-Null } # Create a web client to download the RSS Feed $rss = New-Object -TypeName Net.WebClient # Grab the RSS feed for the MP4 downloads Write-Host "Downloading RSS Feed Information..." -NoNewLine $TechEdRSS = ($rss.downloadstring("http://channel9.msdn.com/Events/TechEd/NorthAmerica/2013/RSS/mp4high")) Write-Host " [COMPLETE]" # Extract the Individual Items from the RSS Feed (easier than working with the long name below) $RssEntries = $TechEdRss.rss.channel.item # Create New Empty Collection for the files to be downloaded $DownloadJobs = @() # Walk through each item in the feed ForEach ( $RssEntry in $RssEntries ) { # Cheater way to build a new object $DownloadObject = "" | Select-Object Type, Code, Source, Destination, Title, TitleNormalized, Author, Summary # Populate the object for the Video File $DownloadObject.Type = "MP4" $DownloadObject.Code = $RssEntry.comments.split("/")[-1] $DownloadObject.Source = $RssEntry.enclosure.url $DownloadObject.Title = $RssEntry.title.Replace('’', "'").Replace('“', '"').Replace('â€', '"') $DownloadObject.TitleNormalized = $DownloadObject.Title.Replace(":", "-").Replace("?", "").Replace("/", "-").Replace("<", "").Replace(">", "").Replace("|", "") $DownloadObject.Author = $RssEntry.creator $DownloadObject.Summary = $RssEntry.summary $DownloadObject.Destination = ( $WorkingDir + "Media" + $DownloadObject.Code + " - " + $Title + ".mp4" ).Replace("’", "'").Replace('–', " - ") $DownloadObject.Destination = ( $WorkingDir + "Media" + $DownloadObject.Code + ".mp4" ).Replace("’", "'").Replace('–', " - ") # Add it to the collection $DownloadJobs += $DownloadObject # Create another empty collection and populate it for the slide decks $DownloadObject = "" | Select-Object Type, Code, Source, Destination, Title, TitleNormalized, Author, Summary $DownloadObject.Type = "PPTX" $DownloadObject.Code = $RssEntry.comments.split("/")[-1] $DownloadObject.Source = $RssEntry.enclosure.url.replace(".mp4", ".pptx") $DownloadObject.Title = $RssEntry.title.Replace('’', "'").Replace('“', '"').Replace('â€', '"') $DownloadObject.TitleNormalized = $DownloadObject.Title.Replace(":", "-").Replace("?", "").Replace("/", "-").Replace("<", "").Replace(">", "").Replace("|", "") $DownloadObject.Author = $RssEntry.creator $DownloadObject.Summary = $RssEntry.summary $DownloadObject.Destination = ( $WorkingDir + "Media" + $DownloadObject.Code + " - " + $DownloadObject.TitleNormalized + ".pptx" ).Replace("’", "'").Replace('–', " - ") $DownloadObject.Destination = ( $WorkingDir + "Media" + $DownloadObject.Code + ".pptx" ).Replace("’", "'").Replace('–', " - ") # Add it to the collection $DownloadJobs += $DownloadObject } $i = 0 # Counter for Progress Bar $NumSessions = $DownloadJobs.Count # Total Items for Progress Bar ForEach ( $DownloadJob in $DownloadJobs | Sort-Object Code | Sort-Object Type -Descending ) { Write-Progress -Activity "Downloading TechEd 2013 Media" -CurrentOperation "Downloading $( $DownloadJob.Title ) to $( $DownloadJob.Destination )" -PercentComplete ( ( $i * 100 ) / $NumSessions ) $code = $DownloadJob.Code # Grab the URL for the file $url = $DownloadJob.Source # Get the "Title" of the Program $Title = $DownloadJob.Title # Create the local file name for the downloads $file = $DownloadJob.Destination # Make sure the file doesn't already exist if ( -not ( Test-Path $file ) ) { # Echo out the file that's being downloaded Write-Host "Bulding Job for: [$file]" try { Start-BitsTransfer -Source $url -Destination $file -DisplayName "$( $DownloadJob.Code ).$( $DownloadJob.Type.ToLower() )" -Description "$( $DownloadJob.Title )" -ErrorAction Ignore } catch { Write-Host "[$url] was not found on the server" -ForegroundColor DarkRed } } else { Write-Host "[$file] already exists!" -ForegroundColor Red } $i++ } Write-Progress -Activity "Downloading TechEd 2013 Media" -Completed # Load the TagLib# Library $TagTypes = Add-Type -Path ( $WorkingDir + "taglib-sharp.dll" ) -PassThru # Cycle through each video download (the Where-Object Clause) and put in tag information from the RSS Feed ForEach ( $DownloadJob in ( $DownloadJobs | Where-Object { $_.Type -eq "MP4" } | Sort-Object Destination ) ) { if ( Test-Path $DownloadJob.Destination ) { $FileTags = [TagLib.File]::Create($DownloadJob.Destination) # Only Update the title and comments tags if they are empty if ( -not ( $FileTags.Tag.Comment ) ) { Write-Host "$( $DownloadJob.Code )`tUpdating Summary: $( $DownloadJob.Summary.Substring(0,80) )..." $FileTags.Tag.Comment = $DownloadJob.Summary } if ( -not ( $FileTags.Tag.Title ) ) { Write-Host "$( $DownloadJob.Code )`tUpdating Title: $( $DownloadJob.Title )" $FileTags.Tag.Title = $DownloadJob.Title } # Update the Artists (Authors) of the Videos $FileTags.Tag.Artists.Clear() $Authors = $DownloadJob.Author.Split(",") Write-Host "$( $DownloadJob.Code )`tAdding Author: $Author" $FileTags.Tag.Artists = $Authors Write-Host "Saving MetaData for $( $DownloadJob.Destination )" -NoNewline $FileTags.Save() Write-Host " [SAVED]" -ForegroundColor Green } else { Write-Host "$( $DownloadJob.Destination ) does not exist." -ForegroundColor Red } }
And that’s how I it’s done!
Dang it, * that’s how it’s done.