尝试编写一个基本的Powershell脚本,该脚本将从URL中提取视频,并在需要的情况下用FFmpeg剪切它们。
首先我需要做的一件事是从站点中提取下载选项,看看我是想使用-f best还是-f bestvideo+bestaudio。因此,我需要运行youtube-dl -F [url]并返回输出,但似乎不能不挂起:
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,它可以工作,并将输出直接返回到控制台,但我需要变量中的输出。还值得一提的是,如果我运行上述操作,但没有传递任何参数($YTDLinfo.Arguments = ""),它也可以工作,即使$YTDLinfo.RedirectStandardOutput设置为$true,并且只返回一些youtube-dl关于它如何需要一个url的术语。
解释起来有点混乱,但只有在重定向标准输出并为其提供-F [url]时才会挂起。有什么想法吗?
发布于 2021-08-02 21:47:17
您的问题是,您正在等待进程退出,而没有确保您已经完全使用了它的重定向输出输出first。
也就是说,如果进程创建了多个输出缓冲区值的stdout数据,则.WaitForExit() 调用可能会无限期地等待,这会阻塞进程,直到调用方读取更多的数据。
因此,在$YTDL.StandardOuput.ReadToEnd()之前调用$YTDL.WaitForExit()。
然而,值得后退一步
为了执行youtube-dl**)控制台应用程序(如来自PowerShell的,与它们的stdout和stderr流连接到等效的PowerShell输出流 ),会像在任何shell**中一样调用它们E 131 _directly_,:
# Directly captures youtube-dl's stdout output as an *array of lines*.
$YTDLStdOut = youtube-dl -F $url使用重定向2>来捕获文件中的stderr输出。
或者,使用2>&1捕获stdout和合并在变量中的stderr,并区分哪些输出行来自稍后的哪个流:-is [string]意味着stdout -参见这个答案。
有关通过直接调用控制台程序捕获stdout和stderr的全面概述,请参见这个答案。
具体来说,通常应该避免使用调用控制台应用程序:
- `Start-Process` is essentially a PowerShell-friendly wrapper around the [`System.Diagnostics.Process`](https://learn.microsoft.com/en-US/dotnet/api/System.Diagnostics.Process) .NET API that you're using.https://stackoverflow.com/questions/68627776
复制相似问题