我正在编写C++代码,其中在执行其中实现的一些操作之后生成N个不同帧的序列.每个帧完成后,我将它作为IMG_%d.png写在磁盘上,最后我使用x264编解码器通过ffmpeg将它们编码为视频.
该程序主要部分的汇总伪代码如下:
std::vector<int> B(width*height*3);
for (i=0; i<N; i++)
{
// void generateframe(std::vector<int> &, int)
generateframe(B, i); // Returns different images for different i values.
sprintf(s, "IMG_%d.png", i+1);
WriteToDisk(B, s); // void WriteToDisk(std::vector<int>, char[])
}
Run Code Online (Sandbox Code Playgroud)
这种实现的问题是所需帧的数量N通常很高(N~100000)以及图像的分辨率(1920x1080),导致磁盘过载,产生数十GB的写入周期每次执行后.
为了避免这种情况,我一直试图找到关于将存储在向量B中的每个图像直接解析为编码器(如x264)的文档(无需将中间图像文件写入磁盘).虽然发现了一些有趣的话题,但没有一个能够专门解决我想要的内容,因为其中许多都涉及在磁盘上使用现有图像文件执行编码器,而其他人则提供其他编程语言(如Python)的解决方案(在这里你)可以为该平台找到一个完全令人满意的解决方案.
我想要获得的伪代码类似于:
std::vector<int> B(width*height*3);
video_file=open_video("Generated_Video.mp4", ...[encoder options]...);
for (i=0; i<N; i++)
{
generateframe(B, i+1);
add_frame(video_file, B);
}
video_file.close();
Run Code Online (Sandbox Code Playgroud)
根据我在相关主题上所读到的内容,x264 C++ API可能能够做到这一点,但是,如上所述,我没有找到满意的答案来解决我的具体问题.我尝试直接学习和使用ffmpeg源代码,但是它的低易用性和编译问题都迫使我放弃这种可能性,因为我只是一个非专业的程序员(我把它视为一种爱好而不幸的是我不能浪费很多时候学习如此苛刻的东西).
我想到的另一个可能的解决方案是找到一种方法在C++代码中调用ffmpeg二进制文件,并以某种方式设法将每次迭代的图像数据(存储在B中)传输到编码器,让每个帧的添加(即,不是"关闭"要写入的视频文件)直到最后一帧,以便可以添加更多帧直到到达第N个帧,其中视频文件将被"关闭".换句话说,通过C++程序调用ffmpeg.exe将第一帧写入视频,但让编码器"等待"更多帧.然后再次调用ffmpeg添加第二帧并使编码器再次"等待"以获得更多帧,依此类推,直到到达最后一帧,视频将完成.但是,我不知道如何进行或者实际上是否可行.
编辑1:
正如回复中所建议的那样,我一直在记录有关命名管道的信息,并尝试在我的代码中使用它们.首先,应该注意我正在使用Cygwin,所以我的命名管道是在Linux下创建的.我使用的修改过的伪代码(包括相应的系统库)如下:
FILE *fd;
mkfifo("myfifo", 0666);
for (i=0; i<N; i++)
{
fd=fopen("myfifo", "wb");
generateframe(B, i+1);
WriteToPipe(B, fd); // void WriteToPipe(std::vector<int>, FILE …Run Code Online (Sandbox Code Playgroud) 我有一个Python脚本,它作为Windows服务运行.该脚本分叉另一个进程:
with subprocess.Popen( args=[self.exec_path], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) as proc:
Run Code Online (Sandbox Code Playgroud)
这会导致以下错误:
OSError: [WinError 6] The handle is invalid
File "C:\Program Files (x86)\Python35-32\lib\subprocess.py", line 911, in __init__
File "C:\Program Files (x86)\Python35-32\lib\subprocess.py", line 1117, in _get_handles
Run Code Online (Sandbox Code Playgroud) 我正在尝试将html5视频转换为mp4视频,并且我是通过PhantomJS随着时间的推移进行屏幕拍摄
我也使用PIL裁剪图像,所以最终我的代码大致是:
while time() < end_time:
screenshot_list.append(phantom.get_screenshot_as_base64())
.
.
for screenshot in screenshot_list:
im = Image.open(BytesIO(base64.b64decode(screenshot)))
im = im.crop((left, top, right, bottom))
Run Code Online (Sandbox Code Playgroud)
现在我正在保存以删除所有这些图像并使用保存文件中的ffmpeg:
os.system('ffmpeg -r {fps} -f image2 -s {width}x{height} -i {screenshots_dir}%04d.png -vf scale={width}:-2 '
'-vcodec libx264 -crf 25 -vb 20M -pix_fmt yuv420p {output}'.format(fps=fps, width=width,
screenshots_dir=screenshots_dir,
height=height, output=output))
Run Code Online (Sandbox Code Playgroud)
但我想要而不是使用那些保存的文件,能够将PIL.Images直接传递给ffmpeg,我该怎么做?
我有一个可用的 python 脚本,它使用 opencv 的视频编写器。
来源https://gist.github.com/stanchiang/b4e4890160a054a9c1d65f9152172600
如果我接收一个文件,无论我只是将视频帧传递给编写器(有效地复制文件)还是尝试编辑该帧,文件总是更大。我希望它不大于原来的(因为如果你读我的脚本,我会模糊很多东西)。
检查他们的元数据后,ffprobe -v quiet -print_format json -show_format -show_streams inputFile.mp4我注意到新文件的比特率比以前高 5.5 倍以上。
来源https://www.diffchecker.com/8r2syeln
由于比特率是文件大小的一个重要决定因素,我想知道是否
我有一个C#应用程序.我有100个JPEG(例如).
我可以轻松地将其编码为视频文件.
当它在客户端应用程序上完成编码后,我将FTP上传到我的服务器.
如果我不能将视频文件写入光盘,而是将其写入内存流(或字节数组)并通过Web服务上传,那将是"更整洁"?
我已经查看了ffmpeg文档,但作为C#开发人员,我觉得理解C示例并不自然.
我想我的第一个问题是可能的,如果是这样,任何人都可以在C#中发布示例代码?目前我在C#中使用进程类来执行ffmpeg.