- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在使用 cv2
编辑图像并使用 FFMPEG 从帧创建视频。有关更多详细信息,请参阅此帖子。
这些图像是 3D RGB NumPy array
s(形状类似于 [h, w, 3]),它们存储在 Python list
中。
是的,我知道 cv2
有一个 VideoWriter
并且我以前使用过它,但这不足以满足我的需求。
简而言之,它只能使用它附带的FFMPEG
版本,该版本不支持CUDA,并且在生成视频时会占用所有CPU时间,而根本不使用任何GPU时间,输出太大了我不能' t 将许多 FFMPEG 参数传递给 VideoWrite
启动。
我下载了 FFMPEG for Windows 的预编译二进制文件,支持 CUDA here,我使用的是 Windows 10 21H1 x64,我的 GPU 是 NVIDIA Geforce GTX 1050 Ti。
无论如何,我需要弄乱所有找到的参数 here 和 there 以找到质量和压缩之间的最佳折衷,如下所示:
command = '{} -y -stream_loop {} -framerate {} -hwaccel cuda -hwaccel_output_format cuda -i {}/{}_%d.png -c:v hevc_nvenc -preset 18 -tune 1 -rc vbr -cq {} -multipass 2 -b:v {} -vf scale={}:{} {}'
os.system(command.format(FFMPEG, loops-1, fps, tmp_folder, file_name, quality, bitrate, frame_width, frame_height, outfile))
我需要完全使用我下载的二进制文件并指定尽可能多的参数以达到最佳结果。
ffmpeg-python
似乎非常适合这项工作,我什至发现
this :我可以将二进制路径作为参数传递给
run
函数
this
import ffmpeg
import io
def vidwrite(fn, images, framerate=60, vcodec='libx264'):
if not isinstance(images, np.ndarray):
images = np.asarray(images)
_,height,width,channels = images.shape
process = (
ffmpeg
.input('pipe:', format='rawvideo', pix_fmt='rgb24', s='{}x{}'.format(width, height), r=framerate)
.output(fn, pix_fmt='yuv420p', vcodec=vcodec, r=framerate)
.overwrite_output()
.run_async(pipe_stdin=True, overwrite_output=True, pipe_stderr=True)
)
for frame in images:
try:
process.stdin.write(
frame.astype(np.uint8).tobytes()
)
except Exception as e: # should probably be an exception related to process.stdin.write
for line in io.TextIOWrapper(process.stderr, encoding="utf-8"): # I didn't know how to get the stderr from the process, but this worked for me
print(line) # <-- print all the lines in the processes stderr after it has errored
process.stdin.close()
process.wait()
return # cant run anymore so end the for loop and the function execution
但是,我需要将所有这些参数以及可能更多的参数传递给进程,并且我不确定这些参数应该传递到哪里(
stream_loop
应该去哪里?
hwaccel
、
hwaccel_output_format
、
multipass
...?)。
最佳答案
如果您已经知道 FFmpeg CLI 的语法,您可以使用我的 following answer 中的 subprocess 模块。 (语法适用于 FFmpeg CLI)。
使用 ffmpeg-python
时包裹:
-i
之前)都在 input(...)
中部分。 -vf
或 -filter_complex
)链接为 filter(...).filter(...).filter(...)
output(...)
中。部分。 'b:v'
,我们必须使用像 **{'b:v': '0'}
这样的字典符号. .overwrite_output()
相当于-y
. hevc_nvenc
应用 H.265 (HEVC) 编解码器。h264_nvenc
(可能需要不同的参数)。 'bgr24'
(不是 'rgb24'
)因为 OpenCV 使用 BGR 排序。 scale
过滤器,使用 CPU 软件缩放。
scale_cuda
筛选。
scale_cuda
,我们必须使用
hwupload_cuda
将帧从 CPU 内存上传到 GPU 内存筛选。
vsync=0, hwaccel='cuda', hwaccel_output_format='cuda'
.
h264_nvenc
的 Python 代码示例编码和
scale_cuda
过滤器(编写编号的帧进行测试):
import cv2
import numpy as np
import ffmpeg
width, height, n_frames, fps = 640, 480, 50, 25 # 50 frames, resolution 640x480, and 25 fps
out_width, out_height = 320, 240 # Downscale to 320x240 (for example).
output_filename = 'output.mp4'
# Set pix_fmt to bgr24, because OpenCV uses BGR ordering (not RGB).
# vcodec='hevc_nvenc' - Select hevc_nvenc codec for NVIDIA GPU accelerated H.265 (HEVC) video encoding.
# hwupload_cuda - upload the frame from CPU memory to GPU memory before using CUDA accelerated scaling filter.
# scale_cuda - Use CUDA (GPU accelerated) scaling filter
# Use dictionary notation due to arguments with colon.
# Execute FFmpeg sub-process using stdin pipe as input.
process = (
ffmpeg
.input('pipe:', vsync=0, hwaccel='cuda', hwaccel_output_format='cuda', format='rawvideo', pix_fmt='bgr24', s=f'{width}x{height}', r=f'{fps}')
.filter('hwupload_cuda') # https://docs.nvidia.com/video-technologies/video-codec-sdk/ffmpeg-with-nvidia-gpu/
.filter('scale_cuda', w=out_width, h=out_height) # CUDA accelerated scaling filter
.filter('setsar', sar=1) # Keep the aspect ratio
.output(output_filename, vcodec='hevc_nvenc', **{'preset:v': '18', 'tune:v': '1', 'rc:v': 'vbr', 'cq:v': '19', 'b:v': '0'}, multipass=2)
.overwrite_output()
.run_async(pipe_stdin=True, overwrite_output=True)
)
# Build synthetic video frames and write them to ffmpeg input stream (for testing):
for i in range(n_frames):
# Build synthetic image for testing ("render" a video frame).
img = np.full((height, width, 3), 60, np.uint8)
cv2.putText(img, str(i+1), (width//2-100*len(str(i+1)), height//2+100), cv2.FONT_HERSHEY_DUPLEX, 10, (255, 30, 30), 20) # Blue number
# Write raw video frame to input stream of ffmpeg sub-process.
process.stdin.write(img.tobytes())
# Close and flush stdin
process.stdin.close()
# Wait for sub-process to finish
process.wait()
关于python - 如何通过 CUDA 支持将 BGR NumPy 数组直接传递给 FFMPEG,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72782178/
我正在尝试创建一个包含 int[][] 项的数组 即 int version0Indexes[][4] = { {1,2,3,4}, {5,6,7,8} }; int version1Indexes[
我有一个整数数组: private int array[]; 如果我还有一个名为 add 的方法,那么以下有什么区别: public void add(int value) { array[va
当您尝试在 JavaScript 中将一个数组添加到另一个数组时,它会将其转换为一个字符串。通常,当以另一种语言执行此操作时,列表会合并。 JavaScript [1, 2] + [3, 4] = "
根据我正在阅读的教程,如果您想创建一个包含 5 列和 3 行的表格来表示这样的数据... 45 4 34 99 56 3 23 99 43 2 1 1 0 43 67 ...它说你可以使用下
我通常使用 python 编写脚本/程序,但最近开始使用 JavaScript 进行编程,并且在使用数组时遇到了一些问题。 在 python 中,当我创建一个数组并使用 for x in y 时,我得
我有一个这样的数组: temp = [ 'data1', ['data1_a','data1_b'], ['data2_a','data2_b','data2_c'] ]; // 我想使用 toStr
rent_property (table name) id fullName propertyName 1 A House Name1 2 B
这个问题在这里已经有了答案: 关闭13年前。 Possible Duplicate: In C arrays why is this true? a[5] == 5[a] array[index] 和
使用 Excel 2013。经过多年的寻找和适应,我的第一篇文章。 我正在尝试将当前 App 用户(即“John Smith”)与他的电子邮件地址“jsmith@work.com”进行匹配。 使用两个
当仅在一个边距上操作时,apply 似乎不会重新组装 3D 数组。考虑: arr 1),但对我来说仍然很奇怪,如果一个函数返回一个具有尺寸的对象,那么它们基本上会被忽略。 最佳答案 这是一个不太理
我有一个包含 GPS 坐标的 MySQL 数据库。这是我检索坐标的部分 PHP 代码; $sql = "SELECT lat, lon FROM gps_data"; $stmt=$db->query
我需要找到一种方法来执行这个操作,我有一个形状数组 [批量大小, 150, 1] 代表 batch_size 整数序列,每个序列有 150 个元素长,但在每个序列中都有很多添加的零,以使所有序列具有相
我必须通过 url 中的 json 获取文本。 层次结构如下: 对象>数组>对象>数组>对象。 我想用这段代码获取文本。但是我收到错误 :org.json.JSONException: No valu
enter code here- (void)viewDidLoad { NSMutableArray *imageViewArray= [[NSMutableArray alloc] init];
知道如何对二维字符串数组执行修剪操作,例如使用 Java 流 API 进行 3x3 并将其收集回相同维度的 3x3 数组? 重点是避免使用显式的 for 循环。 当前的解决方案只是简单地执行一个 fo
已关闭。此问题需要 debugging details 。目前不接受答案。 编辑问题以包含 desired behavior, a specific problem or error, and the
我有来自 ASP.NET Web 服务的以下 XML 输出: 1710 1711 1712 1713
如果我有一个对象todo作为您状态的一部分,并且该对象包含数组列表,则列表内部有对象,在这些对象内部还有另一个数组listItems。如何更新数组 listItems 中 id 为“poi098”的对
我想将最大长度为 8 的 bool 数组打包成一个字节,通过网络发送它,然后将其解压回 bool 数组。已经在这里尝试了一些解决方案,但没有用。我正在使用单声道。 我制作了 BitArray,然后尝试
我们的数据库中有这个字段指示一周中的每一天的真/假标志,如下所示:'1111110' 我需要将此值转换为 boolean 数组。 为此,我编写了以下代码: char[] freqs = weekday
我是一名优秀的程序员,十分优秀!