FFmpeg连接: "不安全的文件名"

138

尝试将一堆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

在这里出了什么问题?在这种情况下,“不安全的文件”一词是什么意思?


78
在“-i”之前添加“-safe 0”。请参见https://ffmpeg.org/ffmpeg-all.html#Options-31。 - Gyan
@Gyan 为什么我使用最新版本后仍需要添加“-safe 0”,即使我之前从未使用过此选项,应用程序也可以正常工作? - Vivek Thummar
4个回答

122

@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),现在似乎可以工作了。太好了!


2
你也可以将 find 子命令更改为 find STREAM -type f -name '*' -printf "file '$PWD/%p'\n"(不要忘记在 ffmpeg 命令中添加 -safe 0)。 - erik
在Windows上我们没有printf,有什么解决方案? - Ricardo Bohner
@RicardoBohner 我现在不在Windows上,但是尝试使用类似 (for %i in (*.wav) do echo file '%i') > concat.txt 的命令。如果你在批处理文件中,请将 % 符号加倍。 - mwfearnley

32

在我的情况下,双引号 导致了错误。

我使用的命令是 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

如果只包含"字母、数字、句点(除前缀)、下划线和连字符",那么上述单引号无引号的情况是安全的。因此,以下常见的文件名将不起作用:

  • 空格
  • 图形符号
  • /(路径)
  • 前缀句点(隐藏文件)

对于这些情况,你仍然需要使用-safe 0

【有关引用和转义的注意事项】

在文件名部分,你总是需要转义 '。原因是因为 file Im' .avi 会自动添加结束引号,变成与 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(无效的媒体文件)之一。


2
在使用文本文件中的文件时,在每个文件名前添加 file 可以解决我的问题。 - hdoghmen

30
为了回答为什么,我们需要查看ffmpeg的分离器如何从输入文件中读取多媒体流。在这种情况下,我们使用“concat”选项,具体如下:(存档文档) 该分离器接受以下选项: safe 如果设置为1,则拒绝不安全的文件路径。如果文件路径不包含协议规范,并且是相对的且所有组件仅包含可移植字符集(字母、数字、句点、下划线和连字符),并且组件开头没有句点,则将其视为安全。
如果设置为0,则接受任何文件名。 默认值为1。 如果格式是自动探测的,则-1等效于1,否则等效于0。
事实证明,find . 命令在文件名前面加上了./。如果您不想使用-safe 0,请参阅如何在Unix的“find”中去掉前导的“./”来解决此问题。

28

@sers的答案完全正确,我只是向您展示了命令,以便您不会在其他地方输入-safe 0。

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接