Powershell中的行继续中间字符串

Line Continuation Mid String In Powershell

我正在尝试在具有两个相同捕获卡的系统上编写一个 FFmpeg 命令,因此我必须使用它们的 "alternate names" 否则 FFmpeg 不明白我在调用哪个。

唯一的问题是备用名称非常长,尤其是通过 dshow 同时调用音频和视频时:

-i video="@device_pnp_\?\usb#vid_07ca&pid_0570&mi_00#7&3886ab1a&0&0000#{65e8773d-8f56-11d0-a3b9-00a0c9223196}\global":audio="@device_cm_{33D9A762-90C8-11D0-BD43-00A0C911CE86}\wave_{0E6F0DEF-2B29-4117-8D30-13F01160AC5B}"

我想在调用音频之前打破这个 "string" 中线以使其更具可读性,如下所示:

-i video="@device_pnp_\?\usb#vid_07ca&pid_0570&mi_00#7&3886ab1a&0&0000#{65e8773d-8f56-11d0-a3b9-00a0c9223196}\global"`
:audio="@device_cm_{33D9A762-90C8-11D0-BD43-00A0C911CE86}\wave_{0E6F0DEF-2B29-4117-8D30-13F01160AC5B}"

但是在这种情况下反引号似乎不起作用,我猜是因为它与字符相邻?如果我和反引号前的 space 它会破坏字符串并且 FFmpeg 错误:

    -i video="@device_pnp_\?\usb#vid_07ca&pid_0570&mi_00#7&3886ab1a&0&0000#{65e8773d-8f56-11d0-a3b9-00a0c9223196}\global" `
:audio="@device_cm_{33D9A762-90C8-11D0-BD43-00A0C911CE86}\wave_{0E6F0DEF-2B29-4117-8D30-13F01160AC5B}"

在 Powershell 中是否可以将其拆分为多行?

编辑 - 全功能命令:

ffmpeg -y -hide_banner -thread_queue_size 9999 -indexmem 9999 -guess_layout_max 0 -f dshow -rtbufsize 2147.48M `
-video_size 1920x1080 -framerate 60 `
-i video="@device_pnp_\?\usb#vid_07ca&pid_0570&mi_00#7&3886ab1a&0&0000#{65e8773d-8f56-11d0-a3b9-00a0c9223196}\global":audio="@device_cm_{33D9A762-90C8-11D0-BD43-00A0C911CE86}\wave_{0E6F0DEF-2B29-4117-8D30-13F01160AC5B}" `
-thread_queue_size 9999 -indexmem 9999 -guess_layout_max 0 -f dshow -rtbufsize 2147.48M `
-video_size 1920x1080 -framerate 60 `
-i video="@device_pnp_\?\usb#vid_07ca&pid_0570&mi_00#7&24df76f&0&0000#{65e8773d-8f56-11d0-a3b9-00a0c9223196}\global":audio="@device_cm_{33D9A762-90C8-11D0-BD43-00A0C911CE86}\wave_{0A494693-5F33-4304-88D7-394757E09648}" `
-map 0:0,0:1 -map 0:1 -map 1:0,1:1 -map 1:1 -c:v h264_nvenc -r 60 -rc-lookahead 120 -forced-idr 1 -strict_gop 1 `
-sc_threshold 0 -flags +cgop -force_key_frames "expr:gte(t,n_forced*2)" -preset: llhp -pix_fmt yuv420p -b:v 250M `
-minrate 250M -maxrate 250M -bufsize 250M -c:a aac -ar 44100 -b:a 384k -ac 2 -af "aresample=async=250" -vsync 1 `
-max_muxing_queue_size 9999 -f segment -segment_time 600 -segment_wrap 9 -reset_timestamps 1 `
-segment_format_options max_delay=0 C:\Users\Jordan\Videos\FFmpeg\FFmpeg%02d.ts

我的目标是打破对视频/音频设备的要求,以更好地适应街区的其他部分。

"..." 字符串的行尾或 PowerShell 中的字符串之间使用 ` not 与使用 [=16] 相同=] for line continuation in Bash 例如:

虽然 ` 确实在 PowerShell 中启用行延续 如果放在一行的最后:

  • 当使用里面一个跨行的"..."字符串时,` 转义换行符,不删除它实际上是无操作 ,鉴于 PowerShell 字符串文字中的换行符不需要转义。

  • 在您的尝试中,使用 between 字符串应该形成 single argument(在一行中直接并排放置的字符串,例如 video="...":audio="..."),` 有效地充当 argument separator,所以你不能分割应该变成一个字符串的方式。[1]

简而言之:在 PowerShell 中

  • 只能在 个参数之间使用续行.

  • 为了在多行中传播单个参数,您需要使用表达式 ((...));允许表达式跨越多行而不继续行。


您的情况的一个选择是 将字符串部分指定为 数组 的元素,稍后 joined 组成一个字符串。

使用一个简化的例子;请注意 -join 技术如何与使用行尾 ` 共存以将命令分布在多行 between arguments:

ffmpeg -framerate 60 `
  -i ((
    'video=@device_pnp_\?', 
    'audio=@device_cm_2'
  ) -join ':') `
  -f dshow

这在执行时转换为以下单行:

ffmpeg -framerate 60 -i video=@device_pnp_\?:audio=@device_cm_2 -f dshow

请注意,您原来的参数内部引号 (video="...":audio="...") 使用,因为它通常不是必需的(尽管某些程序,例如 msiexec,很遗憾需要它)。

PowerShell 按需自动为外部程序的参数添加双引号,即如果它们包含 PowerShell 认为不在 embedded 双引号内的空格。有关更多信息,请参阅 ,包括何时可能出现问题。


另一个替代方法预先构造(仅)长参数并通过变量[引用它们=121=]:

$inputSpec = (
  'video=@device_pnp_\?', 
  'audio=@device_cm_2'
) -join ':'

ffmpeg -framerate 60 -i $inputSpec -f dshow

要通常 将命令的参数分布在多行中而不必在行尾使用 ` between 参数,构造参数在前面的 数组 中,并使用 传递它:

# Construct an array containing all arguments.
# Note: Each parameter (+ operand, if any) is placed on its own line
#       here for clarity, but you're free to choose as many or few 
#       lines desired.
$ffmpegArgs =
  '-y', 
  'hide_banner', 
  '-thread_queue_size', '9999', 
  '-indexmem', '9999', 
  '-guess_layout_max', '0', 
  '-f', 'dshow', 
  '-rtbufsize', '2147.48M',
  '-video_size', '1920x1080', 
  '-framerate', '60',
  '-i', ((
    'video=@device_pnp_\?\usb#vid_07ca&pid_0570&mi_00#7&3886ab1a&0&0000#{65e8773d-8f56-11d0-a3b9-00a0c9223196}\global',        
    'audio=@device_cm_{33D9A762-90C8-11D0-BD43-00A0C911CE86}\wave_{0E6F0DEF-2B29-4117-8D30-13F01160AC5B}'
  ) -join ':')

  # ...

# Pass the array via splatting - note the '@'
ffmpeg @ffmpegArgs

注:

  • Splatting 的主要用例是启用程序化命令参数的构造,并且需要不同的语法,如图所示。

  • This - ultimately rejected - RFC proposal proposed new syntax that would make multi-line continuations with regular argument syntax easier, without needing ` at the end of each interior line; the decision to be reject is here.


[1] 有关 PowerShell 如何解析 复合标记 的详细信息,请参阅 this GitHub issue