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.