Receive-Media.ps1
function Receive-Media { <# .SYNOPSIS Receives Media from an Input .DESCRIPTION Receives media from inputs. .NOTES Stopping a script that is receiving media with CTRL+C may prevent certain filetypes from being finalized. For best results, use a filetype designed for streaming, such as .wav for audio or .mpg for video. Alternatively, if you run Receive-Media -AsJob, stopping the job will normally allow FFMpeg to finalize. .EXAMPLE Receive-Media -DirectShow -VideoDevice "OBS Virtual Camera" -OutputPath .\Desktop.mpg .EXAMPLE Receive-Media -DirectShow -VideoDevice "OBS Virtual Camera" -OutputPath .\Desktop.mkv -AsJob .LINK Send-Media #> param( # The input device type. [Parameter(ParameterSetName='InputDevice',ValueFromPipelineByPropertyName)] [string] $InputType, # The input device identifier. This will be specific to a given input type. [Parameter(ParameterSetName='InputDevice',ValueFromPipelineByPropertyName)] [string] $InputDevice, # If provided, will use a specific pixel format for video and image output. This maps to the -pix_fmt parameter in ffmpeg. [Parameter(ValueFromPipelineByPropertyName)] [Alias('Pix_Fmt')] [string] $PixelFormat, # The frame rate of the outputted video [Parameter(ValueFromPipelineByPropertyName)] [string] $FrameRate, # The number of frames to output. [Parameter(ValueFromPipelineByPropertyName)] [string] $FrameCount, # The duration to record. If not provided, will record indefinitely. [Parameter(ValueFromPipelineByPropertyName)] [Timespan] $Duration, # A list of additional arguments to FFMpeg. [Alias('Arguments','Argument','ArgumentList','FFArgs')] [Parameter(ValueFromRemainingArguments)] [string[]] $FFMpegArgument, # If set, will save output to a file [Parameter(ValueFromPipelineByPropertyName)] [string] $OutputPath, # If set, will run as a background job. [switch] $AsJob, # If set, will limit the number of background jobs to a throttle limit. # By default 5. # Throttling is only available if running on PowerShell Core. [int] $ThrottleLimit, # The path to FFMpeg.exe. By default, checks in the path. [string] $FFMpegPath ) dynamicParam { $myCmd = $MyInvocation.MyCommand Get-RoughDraftExtension -CommandName $myCmd -DynamicParameter } process { if ($AsJob) { # If -AsJob was passed, return & $StartRoughDraftJob # start a background job. } $in = @{} + $PSBoundParameters :receivingMedia do { #region Handle Extensions $extensionArguments = @() Get-RoughDraftExtension -CommandName $myCmd -CanRun -ExtensionParameter $in | . Get-RoughDraftExtension -Run | . { process { $inObj = $_ if ($inObj.ExtensionOutput) { Write-Verbose "Adding Arguments from Extension '$extensionCommand'" Write-Verbose "$($inObj.extensionOutput)" $extensionArguments += $inObj.extensionOutput } if ($inObj.Done) { break receivingMedia } } } #endregion Handle Extensions $allArguments = @() if ($InputType -and $InputDevice) { $allArguments += '-f', $InputType, '-i', $InputDevice } if ($extensionArguments) { $allArguments += $extensionArguments } if ($PixelFormat) { $allArguments += '-pix_fmt', $PixelFormat } if ($FrameRate) { # If -FrameRate was passed $allArguments += "-r" # use '-r' to set it. $allArguments += "$FrameRate" } if ($FrameCount) { $allArguments += "-frames" # use '-r' to set it. $allArguments += "$FrameCount" } elseif ($Duration.TotalMilliseconds -ge 0) { $allArguments += '-t' # then use '-to' to set the end time. $allArguments += "$Duration" } $allArguments += $FFMpegArgument if ($OutputPath) { $allArguments += $OutputPath, '-y' } $ProgId = Get-Random Write-Verbose "FFMpeg Arguments: $allArguments" Use-FFMpeg -FFMpegArgument $allArguments -FFMpegPath $FFMpegPath | ForEach-Object { $outLine = $_ Write-Verbose $outLine $progress = $outLine | & ${?<FFMpeg_Progress>} -Extract if ($progress -and $progress.Time.Totalmilliseconds ) { Write-Progress "Receiving Media" "$($progress.Time)" -Id $ProgId } } Write-Progress "Receiving Media" " " -Id $ProgId -Completed } while ($false) } } |