I watch and download a lot of videos from Channel 9 and because I’m a developer and always looking for ways to speed up anything
I do I searched for a PowerShell script. I eventually found one (can’t remember where) and immediately set it up to download This
Week on Channel 9 and Ping Show. Over time I have added many other shows, events and series. The initial script
I was found with some modifications was
$url="http://channel9.msdn.com/Shows/This+Week+On+Channel+9/feed/mp4high"
$rss=invoke-webrequest -uri $url
$destination="Z:\Media\Videos\ch9\This Week on ch9\"
[xml]$rss.Content|foreach{
$_.SelectNodes("rss/channel/item/enclosure")
}|foreach{
"Checking $($_.url.split("/")[-1]), we will skip it if it already exists in $($destination)"
if(!(test-path ($destination + $_.url.split("/")[-1]))){
"Downloading: " + $_.url
start-bitstransfer $_.url $destination
}
}
Because of the amount of shows growing that I was interested in I added another piece to this. On the root level of all my Channel 9 videos I added a PowerShell
file that would run all the other PowerShell files that looked like
cd Z:\Media\Videos\ch9
$psScripts = Get-ChildItem -Recurse -Filter "*.ps1" |
ForEach-Object -Process { if($_.Name -ne "Download All.ps1"){
Write-Text "$($_.Name)"; . $_.FullName; } }
Write-Output "Done"
This was working great as I wouldn’t need to go and run multiple files in order to update all my videos. Recently because of all the new stuff
that was released because of the announcements at #VS2013Launch
I had to add about 5 new feeds to my collection. This took quite a while as I needed to create a new folder for the show, then get a copy of the first PowerShell script
above and then alter the feed url and location to save the videos to. This lead to yet another script, the way I saw it I could either write a script that
automates the create of the folder and script or I could do the longer but right thing and start “fresh”. The script I now run takes in an array of the URL of the show,
series, event or any other type of channel that has an RSS feed, basically everything after http://channel9.msdn.com/.
The new and improved script looks like:
$feedTypeNameList = $("Shows/PingShow","Shows/This+Week+On+Channel+9","Blogs/One-Dev-Minute",
"Shows/Visual-Studio-Toolbox","Shows/Windows-Azure-Friday",
"Events/Visual-Studio/Launch-2013","Series/Application-Insights-for-Visual-Studio-Online",
"Series/Visual-Studio-Online","Series/Visual-Studio-Online-Monaco",
"Series/Visual-Studio-2012-Premium-and-Ultimate-Overview")
$baseSaveLocation = "Z:\Media\Videos\ch9"
$mediaFormat = "high"
$mediaType = "mp4"
$pathToRemoveInvalidFileNameCharsScript = "Z:\_PowerShell\bulk download\Remove-InvalidFileNameChars.ps1"
#------------Don't edit below here----------------#
. "$pathToRemoveInvalidFileNameCharsScript"
foreach($feedTypeName in $feedTypeNameList)
{
$channelType = $feedTypeName.Split("/")[0]
$feedUrl="http://channel9.msdn.com/$($feedTypeName.Trim(
"/"))/RSS/$($mediaType + $mediaFormat)"
$rss=invoke-webrequest -uri $feedUrl
$destination="$baseSaveLocation\$($feedTypeName.Replace(
"/","\").Trim("\"))\"
if (!(Test-Path $destination)) {
New-Item -ItemType directory -Path $destination
}
[xml]$rss.Content|foreach{
$_.SelectNodes("rss/channel/item")
}|foreach{
$url = $_.SelectSingleNode("enclosure").url
$title = $_.SelectSingleNode("title").InnerText
$fileName = $($url.split("/")[-1])
$mp4fileName = $($fileName.Replace(".$mediaType", "") + "-" +
(Remove-InvalidFileNameChars $title.Replace(" ","-")) + ".$mediaType")
$pptxFileName = $mp4fileName.Replace(".$mediaType", ".pptx")
"Checking $mp4fileName, we will skip it if it already exists in $($destination)"
#if we have the file from the previous script rename it or delete it
if(Test-Path ($destination + $fileName))
{
if(!(Test-Path ($destination + $mp4fileName)))
{
"Renaming: " + $fileName
Rename-Item $($destination + $fileName) $($destination + $mp4fileName)
}
else
{
"Deleting: " + $fileName
Remove-Item $($destination + $fileName)
}
}
else
{
#download media if it doesn't exists
if(!(Test-Path ($destination + $mp4fileName)))
{
"Downloading: " + $url
Start-BitsTransfer $url $($destination + $mp4fileName)
}
}
#download pptx if it doesn't exists
if ($channelType -eq "Event") #only attempt to get pptx file for events
{
"Checking $pptxFileName, we will skip it if it already exists in $($destination)"
if(!(Test-Path ($destination + $pptxFileName)))
{
$urlToDownload = $($feedUrl.Replace("RSS/$($mediaType + $mediaFormat)",
"").Replace("channel9.msdn.com/$channelType",
"video.ch9.ms/sessions").ToLower() + $pptxFileName)
"Downloading: " + $urlToDownload
Start-BitsTransfer $urlToDownload $($destination +
$pptxFileName) -ErrorAction SilentlyContinue
}
}
}
}
This script caters for renaming of media files from the old just file name format to including the title in the file name.
In order to add this extra script that I used for trimming funny characters from the file names.
#source - http:
Function Remove-InvalidFileNameChars {
<#
.SYNOPSIS
This is a PowerShell function to remove invalid characters from strings to be used as file names.
.DESCRIPTION
The function takes a string parameter called Name and returns a string that has been stripped
of invalid file name characters, i.e. *, :, \, /.
The Name parameter will also receive input from the pipeline.
.PARAMETER Name
Specifies the file name to strip of invalid characters.
.INPUTS
Parameter Name accepts System.String objects from the pipeline.
.OUTPUTS
System.String. Outpus a string object
.EXAMPLE
Remove-InvalidFileNameChars -Name "<This/name\is*an:illegal?filename>"
PS C:\>Thisnameisanillegalfilename
.NOTES
It would be easiest to copy the function from the script file and place it in your profile.
However, you may also dot-source the script to load the function into PowerShell:
i.e. PS C:\>. .\Remove-InvalidFileNameChars.ps1
#>
[CmdletBinding()]
param([Parameter(Mandatory=$true,
Position=0,
ValueFromPipeline=$true,
ValueFromPipelineByPropertyName=$true)]
[String]$Name
)
return [RegEx]::Replace($Name, "[{0}]" -f
([RegEx]::Escape([String][System.IO.Path]::GetInvalidFileNameChars())), '')
}
Hope this helps others that download Channel 9 videos to watch offline as well
.