Skip to content

Instantly share code, notes, and snippets.

@pcgeek86
Created February 7, 2020 19:51
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pcgeek86/8c7a2646c922936c0809558c144cfe56 to your computer and use it in GitHub Desktop.
Save pcgeek86/8c7a2646c922936c0809558c144cfe56 to your computer and use it in GitHub Desktop.
Retrieves your YouTube video run-time, in hours, using dependency-free PowerShell code
$ErrorActionPreference = 'stop'
function Get-YouTubeChannel {
[CmdletBinding()]
param (
[Parameter(Mandatory = $true)]
[string] $Username,
[Parameter(Mandatory = $true)]
[string] $AccessToken
)
$Uri = 'https://www.googleapis.com/youtube/v3/channels?part=contentDetails&forUsername={1}&access_token={0}' -f $AccessToken, $Username
Invoke-RestMethod -Uri $Uri
}
function Get-YouTubePlaylistItems {
[CmdletBinding()]
[OutputType([String[]])]
param (
[Parameter(Mandatory = $true)]
[string] $PlaylistId,
[Parameter(Mandatory = $true)]
[string] $AccessToken
)
$VideoIdList = [System.Collections.ArrayList]::new()
$NextPageToken = ''
do {
$Result = Invoke-RestMethod -Uri ('https://www.googleapis.com/youtube/v3/playlistItems?pageToken={2}&part=contentDetails&maxResults=50&playlistId={1}&access_token={0}' -f $AccessToken, $PlaylistId, $NextPageToken)
$NextPageToken = $Result.nextPageToken
if ($NextPageToken) { Write-Verbose -Message $NextPageToken }
foreach ($Video in $Result.items) {
$null = $VideoIdList.Add($Video.contentDetails.videoId)
}
} while ($Result.nextPageToken)
return $VideoIdList
}
function Get-YouTubeVideoDetail {
[CmdletBinding()]
param (
[Parameter(Mandatory = $true)]
[System.Collections.ArrayList] $Id,
[Parameter(Mandatory = $true)]
[string] $AccessToken
)
function Add-DurationSecondsProperty {
[CmdletBinding()]
param (
[Parameter(ValueFromPipeline = $true)]
$Object
)
process {
$input | Add-Member -PassThru -MemberType ScriptProperty -Name DurationSeconds -Value {
$RegEx = 'PT(?<Minutes>\d+)M(?<Seconds>\d+)S|PT(?<Seconds>\d+)S|PT(?<Minutes>\d+)M'
$Matched = $this.contentDetails.duration -match $RegEx
if ($Matched) {
$Minutes = [int]$Matches['Minutes']
$Seconds = [int]$Matches['Seconds']
return ($Minutes*60) + $Seconds
}
else { return 0 }
}
}
}
$VideoDetailList = [System.Collections.ArrayList]::new()
$NextPageToken = ''
for ($i = 0; $i -lt $Id.Count; $i += 50) {
$ItemCount = if (($Id.Count - $i) -gt 50) { 50 } else { $Id.Count - $i }
Write-Verbose -Message $ItemCount
$Uri = 'https://www.googleapis.com/youtube/v3/videos?part=contentDetails&pageToken={2}&maxResults=50&id={1}&access_token={0}' -f $AccessToken, ($Id.GetRange($i, $ItemCount) -join ','), $NextPageToken
Write-Verbose -Message $Uri
$VideoDetailResult = Invoke-RestMethod -Uri $Uri
$null = $VideoDetailList.AddRange(($VideoDetailResult.items | Add-DurationSecondsProperty))
$NextPageToken = $VideoDetailResult.nextPageToken
}
return $VideoDetailList
}
# Use the Google oAuth Playground to obtain an access token.
# Make sure the token is generated, with the appropriate oAuth scope for YouTube Data API v3.
# I tested it with just this oAuth scope: https://www.googleapis.com/auth/youtube
$Token = 'PutYourAccessTokenHere'
$Username = 'PutYourYouTubeUsernameHere'
$Channel = Get-YouTubeChannel -Username $Username -AccessToken $Token
$VideoIdList = Get-YouTubePlaylistItems -PlaylistId $Channel.items[0].contentDetails.relatedPlaylists.uploads -AccessToken $Token
$VideoDetailResult = Get-YouTubeVideoDetail -Id $VideoIdList -AccessToken $Token -Verbose
# Result will be the number of hours of play-time
($VideoDetailResult.DurationSeconds | Measure-Object -Sum).Sum/60/60
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment