Using ffmpeg and ffplay piped together in PowerShell
Asked Answered
G

2

7

I have switched my current video project from command prompt to PowerShell so that I can take full advantage of the Tee-Object for a multi output code.

Currently, I have a version of my code working in batch, but I need to add one more feature through a tee. This is my first time using PowerShell, so this is probably a simple fix...

Currently I have figured out how to run ffmpeg and ffplay in PowerShell, and I have a program in batch which takes an ffmpeg output and pipes it to ffplay, and this works just fine. I can also play through ffplay in PS just fine. In PS, this code works:

ffplay -video_size 1280x720 -pixel_format uyvy422 -framerate 60 -i video="Decklink Video Capture"

And as a batch, this code works fine for what I'm doing:

ffmpeg -video_size 1280x720 -pixel_format uyvy422 -framerate 60 -i video="Decklink Video Capture" -c:v libx265 -preset ultrafast -mpegts pipe: | ffplay pipe:

It takes the video I want and plays it through the pipe to the screen. When played through PowerShell, though, the video doesn't even pop up. I don't get any warnings or anything, and it seems to run fine, but I don't get the picture to display.

End goal is to be able to play the video on the host display in full resolution, and publish a lower bitrate to the network, if that helps.

Graphics answered 21/5, 2018 at 20:47 Comment(4)
Toss $ErrorActionPreference = 'Stop' before your ff calls to see if something's being thrown but not displayed.Eba
I went ahead and did this, and the program immediately stopped. I take it there's a deeper issue then?Graphics
Yeah, that's an error being forced to terminate. Wrap the call in a try/catch block and put $_ | Format-List * -Force; Pause in the catch block to see the error recordEba
So I went ahead and did this, and didn't get anything new. I can see things running as it goes, but nothing stops for an error, and I haven't had any light shed on what's going on...Graphics
L
5

The reason you are seeing strange behavior, is that piping in PowerShell does not work the same way as in the old cmd-interpreter/console. Basically it is parsed by PowerShell before being passed on to the next command. You may read more in this GitHub issue about some of the ongoing work to enable two native processes to pass raw byte-streams in PowerShell.

If you are unable to just run your command in a legacy cmd-shell (it would probably be the easiest way), you may use the module Use-RawPipeline.

Install-Module -Name Use-RawPipeline

Then you can construct a command line like this (I've simplified the argument list to just to use a file and skip the decklink-source for brevity):

Invoke-NativeCommand -FilePath .\ffmpeg -ArgumentList @("-i", "C:\temp\testfile.mp4","-f","h264", "pipe:") |
Invoke-NativeCommand -FilePath .\ffplay.exe -ArgumentList @("pipe:") |
Receive-RawPipeline

If you need to add more command to the pipeline, just insert another Invoke-NativeCommand -FilePath <command> before the Receive-RawPipeline.

Note: I am not sure about the performance of this solution, but I have confirmed it will pipe the output of ffmpeg to ffplay and display the encoded stream.

Lanie answered 27/5, 2018 at 9:56 Comment(0)
Z
1

Example that pipes from ffmpeg to x265:

$env:ffmpeg = 'D:\ffmpeg.exe'
$env:x265   = 'D:\x265.exe'
$env:avs    = 'D:\test.avs'
$env:output = 'D:\test.hevc'

$env:ffmpeg_args = '-f yuv4mpegpipe -strict -1 -loglevel fatal -hide_banner'

$env:x265_args = '--crf 18 --output-depth 10 --y4m'

cmd /s /c --% ""%ffmpeg%" -i "%avs%" %ffmpeg_args% - | "%x265%" %x265_args% --output "%output%" -"

In short:

cmd /s /c --% "<cmd style command>"
Zadoc answered 15/11, 2022 at 17:11 Comment(1)
I think this is a good answer because it shows how to pass variables created in the script in the CMD command. Saved me a lot of time!Christabella

© 2022 - 2024 — McMap. All rights reserved.