Private/Get-PatMediaSubtitle.ps1
|
function Get-PatMediaSubtitle { <# .SYNOPSIS Downloads external subtitles for a media item. .DESCRIPTION Internal helper function that downloads all external subtitle files associated with a Plex media item. Retrieves media information to find external subtitle streams, then downloads each subtitle file to the same directory as the media file with appropriate language code and format extension. .PARAMETER RatingKey The Plex rating key of the media item to get subtitles for. .PARAMETER MediaDestinationPath The full path where the media file is saved. Subtitle files will be saved in the same directory with the same base name plus language and format. .PARAMETER ServerUri The base URI of the Plex server for downloading subtitle files. .PARAMETER Token The Plex authentication token for API requests. .PARAMETER ServerName The name of a stored server to use. Alternative to ServerUri/Token. .PARAMETER ItemDisplayName A display name for the media item, used in warning messages when subtitle downloads fail. .OUTPUTS None. Writes warnings for download failures. .EXAMPLE Get-PatMediaSubtitle -RatingKey 1001 -MediaDestinationPath 'E:\Movies\Movie (2020)\Movie (2020).mkv' ` -ServerUri 'http://plex:32400' -Token 'abc123' -ItemDisplayName 'Movie (2020)' Downloads all external subtitles for the media item. .EXAMPLE Get-PatMediaSubtitle -RatingKey 1001 -MediaDestinationPath 'E:\Movies\Movie (2020)\Movie (2020).mkv' ` -ServerName 'HomeServer' -ItemDisplayName 'Movie (2020)' Downloads subtitles using a stored server configuration. #> [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [int] $RatingKey, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string] $MediaDestinationPath, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string] $ServerUri, [Parameter()] [string] $Token, [Parameter()] [string] $ServerName, [Parameter()] [string] $ItemDisplayName ) process { # Build parameters for Get-PatMediaInfo $mediaInfoParameters = @{ RatingKey = $RatingKey ErrorAction = 'Stop' } if ($ServerName) { $mediaInfoParameters['ServerName'] = $ServerName } else { $mediaInfoParameters['ServerUri'] = $ServerUri if ($Token) { $mediaInfoParameters['Token'] = $Token } } try { $mediaInformation = Get-PatMediaInfo @mediaInfoParameters } catch { Write-Warning "Failed to get media info for subtitle download: $($_.Exception.Message)" return } # Check if media has parts with streams (with explicit bounds checks) if (-not $mediaInformation.Media -or $mediaInformation.Media.Count -eq 0) { Write-Verbose "No media found for RatingKey $RatingKey" return } if (-not $mediaInformation.Media[0].Part -or $mediaInformation.Media[0].Part.Count -eq 0) { Write-Verbose "No media parts found for RatingKey $RatingKey" return } # Filter for external subtitle streams (StreamType 3 = subtitle, External = true, has Key for download) $subtitleStreams = $mediaInformation.Media[0].Part[0].Streams | Where-Object { $_.StreamType -eq 3 -and $_.External -and $_.Key } if (-not $subtitleStreams) { Write-Verbose "No external subtitles found for RatingKey $RatingKey" return } # Get base path for subtitle files (media path without extension) $basePath = [System.IO.Path]::ChangeExtension($MediaDestinationPath, $null).TrimEnd('.') foreach ($sub in $subtitleStreams) { $lang = if ($sub.LanguageCode) { $sub.LanguageCode } else { 'und' } $format = if ($sub.Format) { $sub.Format } else { 'srt' } $subtitlePath = "$basePath.$lang.$format" # Build download URL (token passed via header, not URL for security) $subtitleUrl = "$ServerUri$($sub.Key)?download=1" Write-Verbose "Downloading subtitle: $subtitlePath" try { $downloadParameters = @{ Uri = $subtitleUrl OutFile = $subtitlePath ErrorAction = 'Stop' } if ($Token) { $downloadParameters['Token'] = $Token } Invoke-PatFileDownload @downloadParameters | Out-Null } catch { $displayName = if ($ItemDisplayName) { $ItemDisplayName } else { "RatingKey $RatingKey" } Write-Warning "Failed to download subtitle for '$displayName': $($_.Exception.Message)" } } } } |