ffmpeg concat:“不安全的文件名”

Posted

技术标签:

【中文标题】ffmpeg concat:“不安全的文件名”【英文标题】:ffmpeg concat: "Unsafe file name" 【发布时间】:2016-12-24 03:05:25 【问题描述】:

试图将一堆 mts 文件转换成一个大的 mp4 文件:

stephan@rechenmonster:/mnt/backupsystem/archive2/Videos/20151222/PRIVATE/AVCHD/BDMV$ ~/bin/ffmpeg-git-20160817-64bit-static/ffmpeg -v info -f concat -i <(find STREAM -name '*' -printf "file '$PWD/%p'\n") -deinterlace -r 25 -s hd720 -c:v libx264 -crf 23 -acodec copy -strict -2 ~/tmp/Videos/20151222.mp4
ffmpeg version N-81364-gf85842b-static http://johnvansickle.com/ffmpeg/  Copyright (c) 2000-2016 the FFmpeg developers
  built with gcc 5.4.1 (Debian 5.4.1-1) 20160803
  configuration: --enable-gpl --enable-version3 --enable-static --disable-debug --enable-libmp3lame --enable-libx264 --enable-libx265 --enable-libwebp --enable-libspeex --enable-libvorbis --enable-libvpx --enable-libfreetype --enable-fontconfig --enable-libxvid --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libtheora --enable-libvo-amrwbenc --enable-gray --enable-libopenjpeg --enable-libopus --enable-libass --enable-gnutls --enable-libvidstab --enable-libsoxr --enable-frei0r --enable-libfribidi --disable-indev=sndio --disable-outdev=sndio --enable-librtmp --enable-libmfx --enable-libzimg --cc=gcc-5
  libavutil      55. 28.100 / 55. 28.100
  libavcodec     57. 53.100 / 57. 53.100
  libavformat    57. 46.101 / 57. 46.101
  libavdevice    57.  0.102 / 57.  0.102
  libavfilter     6. 51.100 /  6. 51.100
  libswscale      4.  1.100 /  4.  1.100
  libswresample   2.  1.100 /  2.  1.100
  libpostproc    54.  0.100 / 54.  0.100
[concat @ 0x56054a0] Unsafe file name '/mnt/backupsystem/archive2/Videos/20151222/PRIVATE/AVCHD/BDMV/STREAM'
/dev/fd/63: Operation not permitted

你知道这里出了什么问题吗?在这种情况下,术语“不安全文件”是什么意思?

【问题讨论】:

-i 之前添加-safe 0。见ffmpeg.org/ffmpeg-all.html#Options-31 @Gyan 为什么它仍然需要添加-safe 0,即使我使用的是最新版本(我制作了整个应用程序,但我以前从未使用过这个选项并且效果很好)? 【参考方案1】:

要回答为什么,我们需要看看 ffmpeg 的解复用器的操作,它从输入文件中读取多媒体流。在这种情况下,我们使用“concat”,具有以下选项:(archived docs)

此分路器接受以下选项:

safe 如果设置为 1,拒绝不安全的文件路径。考虑文件路径 如果它不包含协议规范并且是相对的,则它是安全的 并且所有组件仅包含可移植角色中的角色 设置(字母、数字、句点、下划线和连字符)并且没有 句号在组件的开头。

如果设置为 0,则接受任何文件名。

默认为 1。

如果格式被自动探测,-1 等于 1,否则为 0。

原来find . 在文件前面放了一个./。如果您不想使用-safe 0,请参阅How to strip leading "./" in unix "find"? 以获取解决方案。

【讨论】:

【参考方案2】:

在我的例子中,双引号会导致错误。

我使用ffmpeg -f concat -i concat.txt -c copy output.m4a 命令,其中concat.txt 包含要连接的输入文件列表。

不安全的文件名(双引号被视为文件名的一部分,-safe 0 无法解决此问题):

file "song1.m4a"
file "song2.m4a"

安全文件名(单引号):

file 'song1.m4a'
file 'song2.m4a'

安全文件名(不带引号):

file song1.m4a
file song2.m4a

上面的单引号不带引号只有在只包含"letters, digits, period(except prefix), underscore and hyphen"时才是安全的。所以下面的通用文件名将不起作用:

空间 字形 /(路径) 前缀句点(隐藏文件)

对于这种情况,您仍然需要 -safe 0

[Caveat about Quoting and escaping]

你总是需要在文件名部分转义'。原因是file Im' .avi 会自动将结束引号添加到Im' .avi',这与file Im' .avi' 相同。 file Im' .avi'''''' 中的最后一个奇数引号也将添加结束引号变为 file Im' .avi''''''' ,因此它没有 No such file or directory 错误。我发现这种现象是因为空间不再需要在带有单引号的前缀后通过\ 转义,而不必添加结束引号。

尽管有上述(必须通过\ 转义',而不是用" 转义),转义方式类似于shell。如果文件名包含单引号,您可以使用I\'m\ .m4a(不被单引号括起来)样式或'I'\''m .m4a''I'\''m'\ '.m4a'(被单引号括起来)样式转义它,但既不是'I\'m\ .m4a' 也不是'I'm .m4a' .

在测试 ffmpeg 时,请注意第一行 错误消息 Impossible to open 可能会产生误导(该文件确实存在),您需要检查第二行是No such file or directory(文件不存在)或Invalid data found when processing input(无效的媒体文件)。

【讨论】:

在每个文件名前添加 file 解决了我在使用文本文件中的文件时遇到的问题。【参考方案3】:

@sers 的回答完全正确,我只是向您展示命令,因此您不要将 -safe 0 放在其他任何地方。

ffmpeg.exe -f concat -safe 0 -i "clips.txt" -c copy "video.mp4"

【讨论】:

【参考方案4】:

@Mulvya(谢谢!)给出的答案有效:“在-i 之前添加-safe 0”。 然后find STREAM -name '*' -printf "file '$PWD/%p'\n" 出现了另一个问题,它将空路径作为第一个条目返回。将其更改为for f in ./*.wav; do echo "file '$PWD/$f'"; done(请参阅https://trac.ffmpeg.org/wiki/Concatenate),现在它似乎可以工作了。万岁!

【讨论】:

您也可以将find 子命令更改为find STREAM -type f -name '*' -printf "file '$PWD/%p'\n"(不要忘记将-safe 0 添加到ffmpeg 命令中)。

以上是关于ffmpeg concat:“不安全的文件名”的主要内容,如果未能解决你的问题,请参考以下文章

FFmpeg用concat合并视频时,文件名中有单引号的转义方法

FFmpeg concat 视频和音频不同步

使用FFmpeg concat过滤器而不是协议,不同的结果[重复]

ffmpeg concat 让视频更长

ffmpeg 声音与 -concat 或 -ss 不同步

ffmpeg concat demuxer 在加入视频时冻结我的视频帧