我想在Jupyter笔记本中使用ffmpeg
和Python,从matplotlib
生成的2000个PNG图像文件创建视频。我在一台Windows7机器上。
框架又窄又高,所以我想把它们垂直切成七个大小相等的"小";瓦片";使用CCD_ 3;瓦片";水平使用hstack
,但我只得到神秘的错误消息:
ffmpeg_path = notebook_directory # Make sure ffmpeg.exe is in notebook directory!
frames_path = 'C:\Users\Username\Desktop'
frames_renamed_path = os.path.join(frames_path, 'renamed')
os.chdir(frames_renamed_path) # Temporarily change current working directory
check_call(
[
os.path.join(ffmpeg_path, 'ffmpeg'),
'-y', # Overwrite output files without asking
'-report', # Write logfile to current working directory
'-hwaccel', 'cuda', # Use GPU acceleration
'-framerate', '60', # Input frame rate
'-i', os.path.join(frames_renamed_path, 'frame%05d.png'), # Path to input frames
#'-r', '60', # Output frame rate
#'-vf', 'pad=ceil(iw/2)*2:ceil(ih/2)*2', # Pad frames to even pixel numbers (required by many codecs)
#'-pix_fmt', 'yuv420p',
'-pix_fmt', 'rgb32', # Use RGB32 pixel format matching MatPlotLib image output
'-filter_complex', # Cut frames into tiles and rearrange (here: 7 horizontal tiles)
'crop=in_w:in_h/7:0:0[tile_1],' # 1st tile from top
+ 'crop=in_w:in_h/7:0:in_h*1/7[tile_2],' # 2nd tile from top
+ 'crop=in_w:in_h/7:0:in_h*2/7[tile_3],' # 3rd tile from top
+ 'crop=in_w:in_h/7:0:in_h*3/7[tile_4],' # 4th tile from top
+ 'crop=in_w:in_h/7:0:in_h*4/7[tile_5],' # 5th tile from top
+ 'crop=in_w:in_h/7:0:in_h*5/7[tile_6],' # 6th tile from top
+ 'crop=in_w:in_h/7:0:in_h*6/7[tile_7],' # 7th tile from top
+ '[tile_1][tile_2][tile_3][tile_4][tile_5][tile_6][tile_7]hstack=7', # Stack tiles horizontally
os.path.join(frames_renamed_path, 'video.mp4') # Path to store output video
]
)
os.chdir(notebook_directory) # Reset current working directory to notebook directory
---------------------------------------------------------------------------
CalledProcessError Traceback (most recent call last)
Input In [10], in <cell line: 9>()
6 frames_renamed_path = os.path.join(frames_path, 'renamed')
7 os.chdir(frames_renamed_path) # Temporarily change current working directory
----> 9 check_call(
10 [
11 os.path.join(ffmpeg_path, 'ffmpeg'),
12 '-y', # Overwrite output files without asking
13 '-report', # Write logfile to current working directory
14 '-hwaccel', 'cuda', # Use GPU acceleration
15 '-framerate', '60', # Input frame rate
16 '-i', os.path.join(frames_renamed_path, 'frame%05d.png'), # Path to input frames
17 #'-pattern_type', 'glob', '-i', os.path.join(frames_renamed_path, '*.png'), # glob not available in Windows by default
18 #'-r', '60', # Output frame rate
19 '-vf', 'pad=ceil(iw/2)*2:ceil(ih/2)*2', # Pad frames to even pixel numbers (required by many codecs)
20 #'-pix_fmt', 'yuv420p',
21 '-pix_fmt', 'rgb32', # Use RGB32 pixel format matching MatPlotLib image output
22 '-filter_complex', # Cut frames into tiles and rearrange (here: 7 horizontal tiles)
23 'crop=in_w:in_h/7:0:0[tile_1],' # 1st tile from top
24 + 'crop=in_w:in_h/7:0:in_h*1/7[tile_2],' # 2nd tile from top
25 + 'crop=in_w:in_h/7:0:in_h*2/7[tile_3],' # 3rd tile from top
26 + 'crop=in_w:in_h/7:0:in_h*3/7[tile_4],' # 4th tile from top
27 + 'crop=in_w:in_h/7:0:in_h*4/7[tile_5],' # 5th tile from top
28 + 'crop=in_w:in_h/7:0:in_h*5/7[tile_6],' # 6th tile from top
29 + 'crop=in_w:in_h/7:0:in_h*6/7[tile_7],' # 7th tile from top
30 + '[tile_1][tile_2][tile_3][tile_4][tile_5][tile_6][tile_7]hstack=7', # Stack tiles horizontally
31 os.path.join(frames_renamed_path, 'video.mp4') # Path to store output video
32 ]
33 )
35 os.chdir(notebook_directory)
File C:Program FilesPython38libsubprocess.py:364, in check_call(*popenargs, **kwargs)
362 if cmd is None:
363 cmd = popenargs[0]
--> 364 raise CalledProcessError(retcode, cmd)
365 return 0
CalledProcessError: Command '['C:\Users\Username\Desktop\ffmpeg\ffmpeg', '-y', '-report', '-hwaccel', 'cuda', '-framerate', '60', '-i', 'C:\Users\Username\Desktop\renamed\frame%05d.png', '-vf', 'pad=ceil(iw/2)*2:ceil(ih/2)*2', '-pix_fmt', 'rgb32', '-filter_complex', 'crop=in_w:in_h/7:0:0[tile_1],crop=in_w:in_h/7:0:in_h*1/7[tile_2],crop=in_w:in_h/7:0:in_h*2/7[tile_3],crop=in_w:in_h/7:0:in_h*3/7[tile_4],crop=in_w:in_h/7:0:in_h*4/7[tile_5],crop=in_w:in_h/7:0:in_h*5/7[tile_6],crop=in_w:in_h/7:0:in_h*6/7[tile_7],[tile_1][tile_2][tile_3][tile_4][tile_5][tile_6][tile_7]hstack=7', 'C:\Users\Username\Desktop\renamed\video.mp4']' returned non-zero exit status 1.
这是ffmpeg
日志输出(裁剪(:
ffmpeg started on 2022-08-04 at 01:17:19
Report written to "ffmpeg-20220804-011719.log"
Log level: 48
Command line:
"C:\Users\Username\Desktop\ffmpeg\ffmpeg" -y -report -hwaccel cuda -framerate 60 -i "C:\Users\Username\Desktop\renamed\frame%05d.png" -vf "pad=ceil(iw/2)*2:ceil(ih/2)*2" -pix_fmt rgb32 -filter_complex "crop=in_w:in_h/7:0:0[tile_1],crop=in_w:in_h/7:0:in_h*1/7[tile_2],crop=in_w:in_h/7:0:in_h*2/7[tile_3],crop=in_w:in_h/7:0:in_h*3/7[tile_4],crop=in_w:in_h/7:0:in_h*4/7[tile_5],crop=in_w:in_h/7:0:in_h*5/7[tile_6],crop=in_w:in_h/7:0:in_h*6/7[tile_7],[tile_1][tile_2][tile_3][tile_4][tile_5][tile_6][tile_7]hstack=7" "C:\Users\Username\Desktop\renamed\video.mp4"
ffmpeg version 2022-07-14-git-882aac99d2-full_build-www.gyan.dev Copyright (c) 2000-2022 the FFmpeg developers
built with gcc 12.1.0 (Rev2, Built by MSYS2 project)
configuration: --enable-gpl --enable-version3 --enable-static --disable-w32threads --disable-autodetect --enable-fontconfig --enable-iconv --enable-gnutls --enable-libxml2 --enable-gmp --enable-bzlib --enable-lzma --enable-libsnappy --enable-zlib --enable-librist --enable-libsrt --enable-libssh --enable-libzmq --enable-avisynth --enable-libbluray --enable-libcaca --enable-sdl2 --enable-libdav1d --enable-libdavs2 --enable-libuavs3d --enable-libzvbi --enable-librav1e --enable-libsvtav1 --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxavs2 --enable-libxvid --enable-libaom --enable-libjxl --enable-libopenjpeg --enable-libvpx --enable-mediafoundation --enable-libass --enable-frei0r --enable-libfreetype --enable-libfribidi --enable-liblensfun --enable-libvidstab --enable-libvmaf --enable-libzimg --enable-amf --enable-cuda-llvm --enable-cuvid --enable-ffnvcodec --enable-nvdec --enable-nvenc --enable-d3d11va --enable-dxva2 --enable-libmfx --enable-libshaderc --enable-vulkan --enable-libplacebo --ena libavutil 57. 29.100 / 57. 29.100
libavcodec 59. 38.100 / 59. 38.100
libavformat 59. 28.100 / 59. 28.100
libavdevice 59. 8.100 / 59. 8.100
libavfilter 8. 45.100 / 8. 45.100
libswscale 6. 8.100 / 6. 8.100
libswresample 4. 8.100 / 4. 8.100
libpostproc 56. 7.100 / 56. 7.100
Splitting the commandline.
Reading option '-y' ... matched as option 'y' (overwrite output files) with argument '1'.
Reading option '-report' ... matched as option 'report' (generate a report) with argument '1'.
Reading option '-hwaccel' ... matched as option 'hwaccel' (use HW accelerated decoding) with argument 'cuda'.
Reading option '-framerate' ... matched as AVOption 'framerate' with argument '60'.
Reading option '-i' ... matched as input url with argument 'C:UsersUsernameDesktoprenamedframe%05d.png'.
Reading option '-vf' ... matched as option 'vf' (set video filters) with argument 'pad=ceil(iw/2)*2:ceil(ih/2)*2'.
Reading option '-pix_fmt' ... matched as option 'pix_fmt' (set pixel format) with argument 'rgb32'.
Reading option '-filter_complex' ... matched as option 'filter_complex' (create a complex filtergraph) with argument 'crop=in_w:in_h/7:0:0[tile_1],crop=in_w:in_h/7:0:in_h*1/7[tile_2],crop=in_w:in_h/7:0:in_h*2/7[tile_3],crop=in_w:in_h/7:0:in_h*3/7[tile_4],crop=in_w:in_h/7:0:in_h*4/7[tile_5],crop=in_w:in_h/7:0:in_h*5/7[tile_6],crop=in_w:in_h/7:0:in_h*6/7[tile_7],[tile_1][tile_2][tile_3][tile_4][tile_5][tile_6][tile_7]hstack=7'.
Reading option 'C:UsersUsernameDesktoprenamedvideo.mp4' ... matched as output url.
Finished splitting the commandline.
Parsing a group of options: global .
Applying option y (overwrite output files) with argument 1.
Applying option report (generate a report) with argument 1.
Applying option filter_complex (create a complex filtergraph) with argument crop=in_w:in_h/7:0:0[tile_1],crop=in_w:in_h/7:0:in_h*1/7[tile_2],crop=in_w:in_h/7:0:in_h*2/7[tile_3],crop=in_w:in_h/7:0:in_h*3/7[tile_4],crop=in_w:in_h/7:0:in_h*4/7[tile_5],crop=in_w:in_h/7:0:in_h*5/7[tile_6],crop=in_w:in_h/7:0:in_h*6/7[tile_7],[tile_1][tile_2][tile_3][tile_4][tile_5][tile_6][tile_7]hstack=7.
Successfully parsed a group of options.
Parsing a group of options: input url C:UsersUsernameDesktoprenamedframe%05d.png.
Applying option hwaccel (use HW accelerated decoding) with argument cuda.
Successfully parsed a group of options.
Opening an input file: C:UsersUsernameDesktoprenamedframe%05d.png.
[image2 @ 00000000005db0c0] Opening 'C:UsersUsernameDesktoprenamedframe00000.png' for reading
[file @ 00000000005f6c00] Setting default whitelist 'file,crypto,data'
[AVIOContext @ 00000000005fed40] Statistics: 28860 bytes read, 0 seeks
<...>
[AVIOContext @ 00000000005fda00] Statistics: 67659 bytes read, 0 seeks
[image2 @ 00000000005db0c0] Probe buffer size limit of 5000000 bytes reached
Input #0, image2, from 'C:UsersUsernameDesktoprenamedframe%05d.png':
Duration: 00:00:25.00, start: 0.000000, bitrate: N/A
Stream #0:0, 80, 1/60: Video: png, rgba(pc), 1200x1857 [SAR 3937:3937 DAR 400:619], 60 fps, 60 tbr, 60 tbn
Successfully opened the file.
[Parsed_crop_0 @ 00000000005fdc40] Setting 'out_w' to value 'in_w'
[Parsed_crop_0 @ 00000000005fdc40] Setting 'out_h' to value 'in_h/7'
[Parsed_crop_0 @ 00000000005fdc40] Setting 'x' to value '0'
[Parsed_crop_0 @ 00000000005fdc40] Setting 'y' to value '0'
[Parsed_crop_1 @ 0000000000607500] Setting 'out_w' to value 'in_w'
[Parsed_crop_1 @ 0000000000607500] Setting 'out_h' to value 'in_h/7'
[Parsed_crop_1 @ 0000000000607500] Setting 'x' to value '0'
[Parsed_crop_1 @ 0000000000607500] Setting 'y' to value 'in_h*1/7'
[Parsed_crop_2 @ 0000000000607880] Setting 'out_w' to value 'in_w'
[Parsed_crop_2 @ 0000000000607880] Setting 'out_h' to value 'in_h/7'
[Parsed_crop_2 @ 0000000000607880] Setting 'x' to value '0'
[Parsed_crop_2 @ 0000000000607880] Setting 'y' to value 'in_h*2/7'
[Parsed_crop_3 @ 0000000000607c00] Setting 'out_w' to value 'in_w'
[Parsed_crop_3 @ 0000000000607c00] Setting 'out_h' to value 'in_h/7'
[Parsed_crop_3 @ 0000000000607c00] Setting 'x' to value '0'
[Parsed_crop_3 @ 0000000000607c00] Setting 'y' to value 'in_h*3/7'
[Parsed_crop_4 @ 00000000005fda00] Setting 'out_w' to value 'in_w'
[Parsed_crop_4 @ 00000000005fda00] Setting 'out_h' to value 'in_h/7'
[Parsed_crop_4 @ 00000000005fda00] Setting 'x' to value '0'
[Parsed_crop_4 @ 00000000005fda00] Setting 'y' to value 'in_h*4/7'
[Parsed_crop_5 @ 0000000002b8f800] Setting 'out_w' to value 'in_w'
[Parsed_crop_5 @ 0000000002b8f800] Setting 'out_h' to value 'in_h/7'
[Parsed_crop_5 @ 0000000002b8f800] Setting 'x' to value '0'
[Parsed_crop_5 @ 0000000002b8f800] Setting 'y' to value 'in_h*5/7'
[Parsed_crop_6 @ 0000000000607d00] Setting 'out_w' to value 'in_w'
[Parsed_crop_6 @ 0000000000607d00] Setting 'out_h' to value 'in_h/7'
[Parsed_crop_6 @ 0000000000607d00] Setting 'x' to value '0'
[Parsed_crop_6 @ 0000000000607d00] Setting 'y' to value 'in_h*6/7'
[Parsed_hstack_7 @ 0000000002b8fb80] Setting 'inputs' to value '7'
Cannot find a matching stream for unlabeled input pad 0 on filter Parsed_crop_1
这里有什么问题?此外,如何解释日志输出末尾的这个神秘错误消息:
Cannot find a matching stream for unlabeled input pad 0 on filter Parsed_crop_1
例如,什么是input pad 0
,为什么是unlabeled
,为什么找不到匹配的流?
(附言:是的,我确实有过度记录代码的习惯。^^(
该错误是由于filter_complex
的错误使用造成的。
- 输出名称(例如
[tile_1]
(和下一个筛选器之间的分隔符应该是;
,而不是,
(逗号语法用于链接直接一个接一个的筛选器( - 应该定义每个滤波器(如
crop=in_w:in_h/7:0:0[tile_1]
(的输入
在每个部分的开头添加[0]
,用于定义";第一输入流";作为滤波器的输入
用[0]crop=in_w:in_h/7:0:0[tile_1]
替换crop=in_w:in_h/7:0:0[tile_1]
,用[0]crop=in_w:in_h/7:0:in_h*1/7[tile_2]
替换crop=in_w:in_h/7:0:in_h*1/7[tile_2]
纠正的代码(使用我的路径(:
from subprocess import check_call
import os
ffmpeg_path = 'C:\FFmpeg\bin' # Make sure ffmpeg.exe is in the directory!
frames_path = 'C:\Users\Rotem\Desktop'
frames_renamed_path = os.path.join(frames_path, 'renamed')
os.chdir(frames_renamed_path) # Temporarily change current working directory
check_call(
[
os.path.join(ffmpeg_path, 'ffmpeg'),
'-y', # Overwrite output files without asking
'-report', # Write logfile to current working directory
'-hwaccel', 'cuda', # Use GPU acceleration
'-framerate', '60', # Input frame rate
'-i', os.path.join(frames_renamed_path, 'frame%05d.png'), # Path to input frames
'-pix_fmt', 'rgb32', # Use RGB32 pixel format matching MatPlotLib image output
'-filter_complex', # Cut frames into tiles and rearrange (here: 7 horizontal tiles)
'[0]crop=in_w:in_h/7:0:0[tile_1];' # 1st tile from top
+ '[0]crop=in_w:in_h/7:0:in_h*1/7[tile_2];' # 2nd tile from top
+ '[0]crop=in_w:in_h/7:0:in_h*2/7[tile_3];' # 3rd tile from top
+ '[0]crop=in_w:in_h/7:0:in_h*3/7[tile_4];' # 4th tile from top
+ '[0]crop=in_w:in_h/7:0:in_h*4/7[tile_5];' # 5th tile from top
+ '[0]crop=in_w:in_h/7:0:in_h*5/7[tile_6];' # 6th tile from top
+ '[0]crop=in_w:in_h/7:0:in_h*6/7[tile_7];' # 7th tile from top
+ '[tile_1][tile_2][tile_3][tile_4][tile_5][tile_6][tile_7]hstack=7', # Stack tiles horizontally
os.path.join(frames_renamed_path, 'video.mp4') # Path to store output video
]
)
更新:
如果输入图像的分辨率太大,我们可以使用scale
滤波器,然后使用split
滤波器:
示例:
check_call(
[
os.path.join(ffmpeg_path, 'ffmpeg'),
'-y', # Overwrite output files without asking
'-report', # Write logfile to current working directory
'-hwaccel', 'cuda', # Use GPU acceleration
'-framerate', '60', # Input frame rate
'-i', os.path.join(frames_renamed_path, 'frame%05d.png'), # Path to input frames
'-pix_fmt', 'rgb32', # Use RGB32 pixel format matching MatPlotLib image output
'-filter_complex', # Cut frames into tiles and rearrange (here: 7 horizontal tiles)
'scale=480:-1,split=7[v0][v1][v2][v3][v4][v5][v6];'
+ '[v0]crop=in_w:in_h/7:0:0[tile_1];' # 1st tile from top
+ '[v1]crop=in_w:in_h/7:0:in_h*1/7[tile_2];' # 2nd tile from top
+ '[v2]crop=in_w:in_h/7:0:in_h*2/7[tile_3];' # 3rd tile from top
+ '[v3]crop=in_w:in_h/7:0:in_h*3/7[tile_4];' # 4th tile from top
+ '[v4]crop=in_w:in_h/7:0:in_h*4/7[tile_5];' # 5th tile from top
+ '[v5]crop=in_w:in_h/7:0:in_h*5/7[tile_6];' # 6th tile from top
+ '[v6]crop=in_w:in_h/7:0:in_h*6/7[tile_7];' # 7th tile from top
+ '[tile_1][tile_2][tile_3][tile_4][tile_5][tile_6][tile_7]hstack=7', # Stack tiles horizontally
os.path.join(frames_renamed_path, 'video.mp4') # Path to store output video
]
)
我使用以下shell命令创建了10个输入PNG图像(用于测试(:
ffmpeg -f lavfi -i testsrc=duration=10:size=1920x1080:rate=1 frame%05d.png
如果您怀疑输入有问题,可以尝试使用合成图像进行测试。