Just as last year, I wrote a PowerShell script using which you can download the PowerPoint decks, and, videos from Microsoft Build’s conference, instead of streaming it (or manually download it one by one). You can choose if you want the decks, or the videos, or both. For the videos you can choose the desired resolution (Low, Medium, High) – of course the higher the resolution, the more space is needed. The script also downloads the description and if there is a session image (if there is one).
A few points to note:
- The slides only once downloaded is ~10GB and with videos (high-resolution), the size goes up to 90.5 GB. So make sure you have enough space.
- By default the download location is “C:\build-2018\”; you can change this to whatever you want, but make sure there is a trailing backslash. Think of this as the ‘base’ folder.
- For each session a sub-folder with the session name will be created in the ‘base’ folder setup in the previous step.
- If a file already exists, it will be skipped.
- As each file is downloaded, it save it in the root folder and once the download is complete, only then moves it in the relevant subfolder.
- If a download fails for some reason to retry it, delete the ‘left over’ file(s) in the base folder and then run the script again. The script itself will ‘eat’ the exception and move on to the next file.
- The video quality parameter is 1 for Low, 2 for Medium, and 3 for High (default).
And if you read through, the script is quite self-explanatory.
# Comments that you should read, before you kick this off. Yes, seriously. :) # 1. Setup the folder where to download using the parameters outlined below # 2. Loop through and get the slides first # 3. Finally, loop through and get the videos last param ( [string]$path = "C:\build-2018\", [switch]$sessionvideo = $true, [int][ValidateRange(1,3)]$videoquality = 3, [switch]$sessiondeck = $true ) [Environment]::CurrentDirectory=(Get-Location -PSProvider FileSystem).ProviderPath $rss = (new-object net.webclient) #Filenames might get long, so keep this short! #$downloadlocation = "D:\build-2018" if (-not (Test-Path $path)) { Write-Host "Folder $fpath dosen't exist. Creating it..." New-Item $path -type directory } set-location $path if($sessiondeck) { # Grab the Slides RSS feed - Build 2018 $slides = ($rss.downloadstring("http://s.ch9.ms/events/build/2018/rss/slides")) # ********** download the decks ********** try { foreach($item in $slides.rss.channel.item) { $code = $item.comments.split("/") | select -last 1 # Get the url for the pptx file $urlpptx = New-Object System.Uri($item.enclosure.url) # make the filename readable $filepptx = $code + " - " + $item.title.Replace(":", "-").Replace("?", "").Replace("/", "-").Replace("<", "").Replace("|", "").Replace('"',"").Replace("*","").Replace("’","'").Replace("â€","").Replace("'NEW SESSION'","").Replace("™","").Replace("œ","") $filepptx = $filepptx.substring(0, [System.Math]::Min(120, $filepptx.Length)) $filepptx = $filepptx.trim() $filejpg = $filepptx $filepptx = $filepptx + ".pptx" $filejpg = $filejpg + "_960.png" $folder = $item.title.Replace(":", "-").Replace("?", "").Replace("/", "-").Replace("<", "").Replace("|", "").Replace('"',"").Replace("*","").Replace("’","'").Replace("â€","").Replace("'NEW SESSION'","").Replace("™","").Replace("œ","") $folder = $folder.substring(0, [System.Math]::Min(100, $folder.Length)) $folder = $folder.trim() if (-not (Test-Path $folder)) { Write-Host "Folder $folder doesnt exist. Creating it..." New-Item $folder -type directory } # Make sure the PowerPoint file doesn't already exist if (!(test-path "$path\$folder\$filepptx")) { # Echo out the file that's being downloaded $filepptx $wc = (New-Object System.Net.WebClient) # Download the pptx file Invoke-WebRequest $urlpptx -OutFile $path\$filepptx # download the jpg but don't want to break if this doesn't exist; hence the nested try blocks try { if($item.thumbnail -ne $null) { $urljpg = New-Object System.Uri($item.thumbnail.url) if (!(test-path "$path\$filejpg")) { $wc.DownloadFile($urljpg, "$path\$folder\$filejpg") } } } catch { Write-Host "Image (jpeg) $filejpg doesn't exist ... eating the exception and moving on ..." } mv $filepptx $folder #mv $filejpg $folder } #endif else { Write-Host "PPTX: $filepptx exist; skipping download." } #try and get the sessions details try { $descriptionFileName = "$($path)\$($folder)\$($Code.trim()).txt" if (!(test-path "$descriptionFileName")) { $OutFile = New-Item -type file $descriptionFileName -Force $Content = "Title: " + $item.title.ToString().trim() + "`r`n" + "`r`n" + "Presenter: " + $item.creator + "`r`n" + "`r`n" + "Summary: " + $item.summary.ToString().trim() + "`r`n" + "`r`n" + "Link: " + $item.comments.ToString().trim() #some categories are missing; so need to eat the exception #this is a hack and not very elegant try { if($item.category -ne $null) { $Content = $Content + "`r`n" + "`r`n" + "Category: " + $item.category.ToString().trim().Replace("+"," ") } } catch { #do nothing; eat the exception } add-content $OutFile $Content } } catch { $ErrorMessage = $_.Exception.Message $FailedItem = $_.Exception.ItemName Write-host "\t" $ErrorMessage + "\n" + $FailedItem } } #end-loop foreach Write-host "*************** Downloading all the decks complete ***************" } catch { Write-host "Oops, could not find any slides." $ErrorMessage = $_.Exception.Message $FailedItem = $_.Exception.ItemName Write-host "\t" $ErrorMessage + "\n" + $FailedItem } } #download session-deck # ********** download the videos ********** # if you don't want the video but only the slides just comment all the code below in the foreach loop try { # check for video download if($sessionvideo) { switch ($videoquality) { 1 {$video = ($rss.downloadstring("http://s.ch9.ms/events/build/2018/rss/mp3")); break} 2 {$video = ($rss.downloadstring("http://s.ch9.ms/events/build/2018/rss/mp4")); break} default {$video = ($rss.downloadstring("http://s.ch9.ms/events/build/2018/rss/mp4high")); break} } foreach($item in $video.rss.channel.item) { # Grab the URL for the MP4 file $url = New-Object System.Uri($item.enclosure.url) # Create the local file name for the video download $file = $item.title.Replace(":", "-").Replace("?", "").Replace("/", "-").Replace("<", "").Replace("|", "").Replace('"',"").Replace("*","").Replace("’","'").Replace("â€","").Replace("'NEW SESSION'","").Replace("™","").Replace("œ","") $file = $file.substring(0, [System.Math]::Min(120, $file.Length)) $file = $file.trim() $file = $file + ".mp4" $folder = $item.title.Replace(":", "-").Replace("?", "").Replace("/", "-").Replace("<", "").Replace("|", "").Replace('"',"").Replace("*","").Replace("’","'").Replace("â€","").Replace("'NEW SESSION'","").Replace("™","").Replace("œ","") $folder = $folder.substring(0, [System.Math]::Min(100, $folder.Length)) $folder = $folder.trim() if (-not (Test-Path $folder)) { Write-Host "Folder $folder doesn't exist. Creating it..." New-Item $folder -type directory } # Make sure the video file doesn't already exist if (!(test-path "$folder\$file")) { # Echo out the file that's being downloaded $file # Download the video file try{ if (!(test-path "$path\$file")) { Invoke-WebRequest $url -OutFile $path\$file #move it from the current working folder to the target mv $file $folder } else { Write-Host "Video: $file - anoter process possibly working on this; skipping download." } } catch { $ErrorMessage = $_.Exception.Message $FailedItem = $_.Exception.ItemName Write-host "\t" $ErrorMessage + "\n" + $FailedItem } } else { Write-Host "Video: $file exist; skipping download." } } #end-loop foreach } #end - video check } catch { Write-host "Oops, could not find any videos or some other error happened." $ErrorMessage = $_.Exception.Message $FailedItem = $_.Exception.ItemName Write-host "\t" $ErrorMessage + "\n" + $FailedItem } # ********** End - download the videos section ********** Write-host "*************** All Done! Woot! ***************"