youtube-dl 进程因 RedirectStandardOutput 而挂起

youtube-dl process hangs with RedirectStandardOutput

正在尝试编写一个基本的 Powershell 脚本,该脚本将从 URL 中提取视频,并在需要时使用 FFmpeg 对其进行剪切。

我需要预先做的一件事是从站点中提取下载选项,看看我是想使用 -f best 还是 -f bestvideo+bestaudio。所以我需要 运行 youtube-dl -F [url] 和 return 输出,但我似乎不能不挂起就这样做:

param(
  [string]$url = "https://www.youtube.com/watch?v=njX2bu-_Vw4"
)

$YTDLinfo = New-Object System.Diagnostics.ProcessStartInfo
$YTDLinfo.FileName = "youtube-dl"
$YTDLinfo.RedirectStandardError = $false
$YTDLinfo.RedirectStandardOutput = $true
$YTDLinfo.UseShellExecute = $false
$YTDLinfo.Arguments = "-F $url"
$YTDL = New-Object System.Diagnostics.Process
$YTDL.StartInfo = $YTDLinfo
$YTDL.Start() | Out-Null
$YTDL.WaitForExit()

$YTDLStdOut = $YTDL.StandardOutput.ReadToEnd().split([Environment]::NewLine)

Write-Host $YTDLStdOut

如果我将 $YTDLinfo.RedirectStandardOutput 更改为 $false 它会起作用并且 return 将输出直接输入控制台,但我需要变量中的输出。另外值得一提的是,如果我 运行 以上但没有传递任何参数($YTDLinfo.Arguments = "")它也可以工作,即使 $YTDLinfo.RedirectStandardOutput 设置为 $true,并且只是 return关于它如何需要 url.

的一些 youtube-dl 行话

解释起来有点混乱,但只有在重定向标准输出并向其提供 -F [url] 时才会挂起。有什么想法吗?

你的立即问题是你在等待进程退出,但没有确保你已经完全使用了它的重定向标准输出先输出.

也就是说,您的 .WaitForExit() 调用可能会无限期地等待 ,即如果进程创建多个输出缓冲区的标准输出数据,阻塞 进程,直到调用者读取更多数据。

因此,在$YTDL.WaitForExit().

之前调用$YTDL.StandardOuput.ReadToEnd()

但是,退一步是值得的:

为了从 PowerShell同步执行控制台应用程序(例如youtube-dl,它们的 stdout 和 stderr 流连接到等效的 PowerShell output streams直接调用它们,就像在任何 shell 中一样:

# Directly captures youtube-dl's stdout output as an *array of lines*.
$YTDLStdOut = youtube-dl -F $url

使用重定向 2> 以在 文件.

中捕获 stderr 输出

或者,使用2>&1捕获stdout和stderr merged在一个变量中,然后区分哪个输出行来自哪个流:-is [string]意味着stdout - 参见 .

有关通过直接调用控制台程序捕获 stdout 和 stderr 的全面概述,请参阅 this answer

具体而言,通常应避免使用以下技术 来调用控制台应用程序:

  • 不要使用Start-Process(异常情况除外)-参见this answer.

  • 不要使用Invoke-Expression, which should be avoided in general - see .