使用 ffmpeg 创建视频

2024-03-16

我有 100 张图像(PNG),我想使用这些图像创建一个视频。我为此使用 ffmpeg 库。使用命令行我可以轻松创建视频。但是我如何通过编码来做到这一点呢?

任何帮助将不胜感激。

#pragma GCC diagnostic ignored "-Wdeprecated-declarations"


#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#ifdef HAVE_AV_CONFIG_H
#undef HAVE_AV_CONFIG_H
#endif

extern "C"
{
#include "libavutil/imgutils.h"
#include "libavutil/opt.h"
#include "libavcodec/avcodec.h"
#include "libavutil/mathematics.h"
#include "libavutil/samplefmt.h"
}

#define INBUF_SIZE 4096
#define AUDIO_INBUF_SIZE 20480
#define AUDIO_REFILL_THRESH 4096




static void video_encode_example(const char *filename, int codec_id)
{
   AVCodec *codec;
   AVCodecContext *c= NULL;
   int i, out_size, size, x, y, outbuf_size;
   FILE *f;
   AVFrame *picture;
   uint8_t *outbuf;
   int nrOfFramesPerSecond  =25;
   int nrOfSeconds =1;


   printf("Video encoding\n");

//    find the mpeg1 video encoder
   codec = avcodec_find_encoder((CodecID) codec_id);
   if (!codec) {
       fprintf(stderr, "codec not found\n");
       exit(1);
   }

   c = avcodec_alloc_context3(codec);
   picture= avcodec_alloc_frame();

//    put sample parameters
   c->bit_rate = 400000;
//    resolution must be a multiple of two
   c->width = 352;
   c->height = 288;
//    frames per second
   c->time_base= (AVRational){1,25};
   c->gop_size = 10;  //emit one intra frame every ten frames
   c->max_b_frames=1;
   c->pix_fmt = PIX_FMT_YUV420P;

   if(codec_id == CODEC_ID_H264)
       av_opt_set(c->priv_data, "preset", "slow", 0);

//    open it
   if (avcodec_open2(c, codec, NULL) < 0) {
       fprintf(stderr, "could not open codec\n");
       exit(1);
   }

   f = fopen(filename, "wb");
   if (!f) {
       fprintf(stderr, "could not open %s\n", filename);
       exit(1);
   }

//    alloc image and output buffer
   outbuf_size = 100000;
   outbuf = (uint8_t*) malloc(outbuf_size);

//    the image can be allocated by any means and av_image_alloc() is
//    * just the most convenient way if av_malloc() is to be used
   av_image_alloc(picture->data, picture->linesize,
                  c->width, c->height, c->pix_fmt, 1);

//    encode 1 second of video
   int nrOfFramesTotal = nrOfFramesPerSecond * nrOfSeconds;

//    encode 1 second of video
   for(i=0;i < nrOfFramesTotal; i++) {
       fflush(stdout);
//        prepare a dummy image

       for(y=0;y<c->height;y++) {
           for(x=0;x<c->width;x++) {
               picture->data[0][y * picture->linesize[0] + x] = x + y + i * 3;
           }
       }

//        Cb and Cr
       for(y=0;y<c->height/2;y++) {
           for(x=0;x<c->width/2;x++) {
               picture->data[1][y * picture->linesize[1] + x] = 128 + y + i * 2;
               picture->data[2][y * picture->linesize[2] + x] = 64 + x + i * 5;
           }
       }

//        encode the image
       out_size = avcodec_encode_video(c, outbuf, outbuf_size, picture);
       printf("encoding frame %3d (size=%5d)\n", i, out_size);
       fwrite(outbuf, 1, out_size, f);
   }

//    get the delayed frames
   for(; out_size; i++) {
       fflush(stdout);

       out_size = avcodec_encode_video(c, outbuf, outbuf_size, NULL);
       printf("write frame %3d (size=%5d)\n", i, out_size);
       fwrite(outbuf, 1, out_size, f);
   }

//    add sequence end code to have a real mpeg file
   outbuf[0] = 0x00;
   outbuf[1] = 0x00;
   outbuf[2] = 0x01;
   outbuf[3] = 0xb7;
   fwrite(outbuf, 1, 4, f);
   fclose(f);
   free(outbuf);

   avcodec_close(c);
//   av_free(c);
//   av_free(picture->data[0]);
//   av_free(picture);
   printf("\n");
}

int main(int argc, char **argv)
{
   const char *filename;


   avcodec_register_all();

   if (argc <= 1) {

       video_encode_example("/home/radix/Desktop/OpenCV/FFMPEG_Output/op89.png", AV_CODEC_ID_H264);
   } else {
       filename = argv[1];
   }


   return 0;
}
  • 每次搜索时我都会得到与此类似的代码。但我不明白如何使用它从图像创建视频。

这种情况一次又一次出现的原因是因为你正在使用编码示例.c https://ffmpeg.org/doxygen/trunk/encoding-example_8c-source.html作为你的参考。请不要这样做。此示例中最根本的错误是它没有教您编解码器和容器之间的区别。事实上,它完全忽略了容器。

什么是编解码器?编解码器是一种压缩媒体类型的方法。例如,H264 将压缩原始视频。想象一下 1080p 视频帧,通常采用 YUV 格式,具有 4:2:0 色度子采样。原始的,这是每帧 1080*1920*3/2 字节,即 ~3MB/f。对于 60fps,这是 180MB/秒,或 1.44 千兆位/秒 (gbps)。这是很多数据,所以我们对其进行压缩。在该分辨率下,您可以为 H264、HEVC 或 VP9 等现代编解码器以几兆比特/秒 (mbps) 的速度获得相当好的质量。对于音频,AAC 或 Opus 等编解码器很流行。

什么是容器?容器获取视频或音频(或字幕)数据包(压缩或未压缩)并将它们交错以组合存储在单个输出文件中。因此,您获得的不是一个视频文件和一个音频文件,而是一个交错数据包的文件。这允许有效的搜索和索引,通常还允许添加元数据存储(“作者”、“标题”)等。流行容器的示例有 MOV、MP4(实际上就是 mov)、AVI、Ogg、Matroska 或 WebM(实际上就是 matroska)。

(如果需要,您可以将纯视频数据存储在文件中。对于 H264,这称为“annexb”原始 H264。这实际上就是您上面所做的。那么为什么它不起作用?好吧,您忽略了像 SPS 和 PPS 这样的“标头”数据包。这些位于 avctx->extradata 中,需要在第一个视频数据包之前写入。使用容器可以为您解决这个问题,但您没有,所以它没有工作。)

如何在 FFmpeg 中使用容器?参见例如this https://stackoverflow.com/questions/34823545/cutting-mpeg-ts-file-via-ffmpegwrapper/34984037#34984037帖子,特别是调用函数的部分,例如avformat_write_*()(基本上任何听起来像输出的东西)。我很高兴回答更具体的问题,但我认为上面的帖子应该可以消除您的大部分困惑。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 ffmpeg 创建视频 的相关文章

  • 具有可绑定属性的自定义视图未在 Xamarin.Forms SAP 上正确绑定

    我有一个复选框 应该触发按钮的 IsEnabled 事件 但不知何故 应该执行的命令永远不会正确绑定并因此执行 这是 CheckBox xaml cs 控件 中的可绑定属性 public static readonly BindablePr
  • setContextProperty 和对象的 setProperty 之间的区别

    我现在真的很困惑 有什么区别 QQmlApplicationEngine engine engine rootContext setContextProperty myObject userData and object gt setPro
  • 将图像文件从网址复制到本地文件夹?

    我有该图像的网址 例如 http testsite com web abc jpg http testsite com web abc jpg 我想将该 URL 复制到 c images 中的本地文件夹中 而且当我将该文件复制到文件夹中时
  • 用户控件内所有控件均为空

    我有一个 UserControl 它使用 UserControl 以及其他控件 In the ascx文件我有以下代码
  • 如何在编译C代码时禁用警告?

    我正在使用 32 位 Fedora 14 系统 我正在使用编译我的源代码gcc 有谁知道如何在编译c代码时禁用警告 EDIT 是的 我知道 最好的办法是修复这些警告以避免任何未定义 未知的行为 但目前在这里 我第一次编写了巨大的代码 并且在
  • Qt 计算和比较密码哈希

    目前正在 Qt 中为测验程序构建面向 Web 的身份验证服务 据我了解 在数据库中存储用户密码时 必须对其进行隐藏 以防落入坏人之手 流行的方法似乎是添加的过程Salt https en wikipedia org wiki Salt cr
  • 有没有办法使用 i387 fsqrt 指令获得正确的舍入?

    有没有办法使用 i387 fsqrt 指令获得正确的舍入 除了改变精确模式在 x87 控制字中 我知道这是可能的 但这不是一个合理的解决方案 因为它存在令人讨厌的重入型问题 如果 sqrt 操作中断 精度模式将出错 我正在处理的问题如下 x
  • 序列化和反序列化 Visual Studio 解决方案文件 - 或以编程方式编辑?

    我想以编程方式添加和删除项目 解决方案文件夹和其他项目 例如解决方案的资源文件 但我不确定最好的方法是什么 对于那些不知道的人 高度简化 解决方案文件 sln 通常如下所示 Microsoft Visual Studio Solution
  • C# datagridview 列转入数组

    我正在用 C 构建一个程序 并在其中包含一个 datagridview 组件 datagridview 有固定数量的列 2 我想将其保存到两个单独的数组中 但行数确实发生了变化 我怎么能这样做呢 假设一个名为 dataGridView1 的
  • 无法加载文件或程序集“EntityFramework,版本=6.0.0.0”

    我究竟做错了什么 我该如何解决这个问题 我有一个包含多个项目的解决方案 它是一个 MVC NET 4 5 Web 应用程序 在调试模式下启动后调用其中一个项目时 出现此错误 导致此错误的项目具有以下参考 两个都是版本6 0 0 0 应用程序
  • C#中Enum中定义的value__是什么

    What value 可能在这里 value MSN ICQ YahooChat GoogleTalk 我运行的代码很简单 namespace EnumReflection enum Messengers MSN ICQ YahooChat
  • 在简单注入器中注册具有多个构造函数和字符串依赖项的类型

    我正在尝试弄清楚如何使用 Simple Injector 我在项目中使用了它 注册简单服务及其组件没有任何问题 但是 当组件具有两个以上实现接口的构造函数时 我想使用依赖注入器 public DAL IDAL private Logger
  • 使用 AdHocWorkspace 会导致“不支持语言‘C#’”。

    在VS2015中使用Microsoft CodeAnalysis CSharp Workspaces的RC2 这段代码会抛出异常 var tree CSharpSyntaxTree ParseText var workspace new A
  • 如何用 C 语言练习 Unix 编程?

    经过五年的专业 Java 以及较小程度上的 Python 编程并慢慢感觉到我的计算机科学教育逐渐消失 我决定要拓宽我的视野 对世界的一般用处 并做一些 对我来说 感觉更重要的事情就像我真的对机器有影响一样 我选择学习 C 和 Unix 编程
  • .NET JIT 编译的代码缓存在哪里?

    NET 程序首先被编译为 MSIL 代码 当它被执行时 JIT编译器会将其编译为本机机器代码 我想知道 这些JIT编译的机器代码存储在哪里 它只存储在进程的地址空间中吗 但由于程序的第二次启动比第一次快得多 我认为即使在执行完成后 该本机代
  • TPL 数据流块下游如何获取源生成的数据?

    我正在使用 TPL Dataflow 处理图像 我收到处理请求 从流中读取图像 应用多次转换 然后将生成的图像写入另一个流 Request gt Stream gt Image gt Image gt Stream 为此 我使用块 Buff
  • 如何将对象转换为传递给函数的类型?

    这不会编译 但我想做的只是将对象转换为传递给函数的 t public void My Func Object input Type t t object ab TypeDescriptor GetConverter t ConvertFro
  • 使用 Chrome 和 Selenium 设置 LocalStorage

    我正在尝试使用 OpenQA Selenium 和 Chrome 设置本地存储键和值 我认为这相当微不足道 但我似乎无法让它发挥作用 我对 C 很陌生 所以我可能错过了一些东西 无论如何 我有这个功能 public static void
  • C# 粘贴到文本框时检查剪贴板中的字符

    有没有一些方法可以在粘贴到文本框 C 之前仅检查剪贴板中的字符 Ctrl V 和右键单击 gt 粘贴 但不使用 MaskedTextbox 在文本框文本更改中添加规则以仅接受数字 例如 private string value privat
  • 新的 .NET 6 控制台模板中的 C# 函数重载不起作用

    我在尝试重载该函数时遇到错误Print object in the 新的 NET 6 C 控制台应用程序模板 https learn microsoft com en us dotnet core tutorials top level t

随机推荐

  • 如何在mysql中使用sql join

    表名 tbl schedule tr id P K mr id F K sch date doctor id 1 23 01 01 2012 32 2 23 05 01 2012 13 3 22 08 01 2012 14 表名 tbl u
  • Boost - 子进程仍然是僵尸进程

    我编写了简单的代码 以分离的方式运行子进程 boost process child childProcess sleep 10 boost process std in close boost process std out close c
  • 在 Github 上托管 ipython 笔记本

    我维护一个 Github 存储库 当前包含两个 ipython 笔记本文件 我的存储库在这里 https github com tschm MosekRegression https github com tschm MosekRegres
  • 不可重现的 R 包可用性检查

    在检查软件包向量是否需要安装时 我遇到了一个有趣的错误 要求并卸载 lme4 命名空间会在第二次执行时出现错误 但仅当按特定顺序检查其他一些包时才会出现错误 isInstalled lt function package is a pack
  • 有没有办法在Python中使用PhantomJS?

    我想用PhantomJS http phantomjs org in Python http www python org 我用谷歌搜索了这个问题但找不到正确的解决方案 I find os popen 可能是一个不错的选择 但我无法向它传递
  • 具有多个数据库服务器的 ServiceStack OrmLite

    我正在围绕服务堆栈框架构建一个应用程序 并且需要能够访问 Oracle 和 MS Sql Server 中的数据 使用 ORMLite 是否可以做到这一点 似乎我只能为应用程序设置一种方言 或者我错过了什么 是的 这是可能的 并且对此的支持
  • 在 Spring Boot 中全局启用 CORS

    我尝试像这样全局启用 CORS Configuration ComponentScan com example EnableWebMvc public class OriginFilter extends WebMvcConfigurerA
  • 无法在装饰器中捕获 pytest 的结果

    我的 pytest 测试装饰器在调用函数后立即退出装饰器 如果我使用 python 而不是 pytest 运行该文件 效果会很好 这是代码 def dec func def wrapper args kwargs print do some
  • JFreeChart 不会在线程上的每次迭代时显示图形?

    我使用线程在一个类中获取计数器值并写入JFreeChart在另一个线程中 执行时 它交替工作 但只显示最后的图形 它还将 y 轴标签值显示为 Float 但实际检索值是 int 我该如何解决这些问题 XYDataset Dataset Ti
  • 在 Rails 中,哪里是放置需要“随处”可用的方法的正确位置

    我已经将许多小实用方法 例如用于重新格式化或解析字符串等简单对象 放入了 ApplicationHelper 中 但是 模型中的类方法显然无法访问 ApplicationHelper 方法 有一个解决方法 那就是在我的项目中进行洒水 inc
  • 在 Java 中动态加载模块(类)的最佳方法

    我目前正在编写一个需要在不同类型的设备上运行的应用程序 我的方法是制作一个 模块化 应用程序 可以根据需要操作的设备动态加载不同的类 为了使应用程序易于扩展 我的目标是为附加模块 jar 或 class 文件 分配特定路径 而核心程序保持原
  • 如何获取和设置当前网页滚动位置?

    如何获取和设置当前网页滚动位置 我有一个很长的表单 需要根据用户操作 输入进行刷新 发生这种情况时 页面会重置到最顶部 这对用户来说很烦人 因为他们必须向下滚动回到原来的位置 如果我可以在页面重新加载之前捕获当前滚动位置 在隐藏输入中 那么
  • 如何列出包中的所有类和方法/函数 - 具有完整的文件夹/文件路径?

    为了更好地理解包的结构 假设我们有一些包 模块 比如说 somemodule 结构如下 somemodule file1 py fo x a function file2 py bar x a function dir1 file3 py
  • 在 Rails 应用程序中实现投票的最佳方式?

    目前在 Rails 站点上实现投票的最佳插件是什么 我知道的两个是 vote fu http github com peteonrails vote fu 行为可投票 http github com ryanto acts as votab
  • JPA CriteriaBuilder 案例查询

    任何人都可以提供如何使用编写案例查询的示例CriteriaBuilder 以下是使用的示例案例表达式CriteriaBuilder 这适用于 JPA 2 Hashtable caseTable new Hashtable 3 caseTab
  • Jquery视差滚动效果-多方向

    我需要为客户构建一个多方向 JQuery 视差页面 他们基本上希望它以与此类似的方式工作 https victoriabeckham landrover com INT https victoriabeckham landrover com
  • 从 shell 脚本获取 pytest 退出代码

    我正在从 shell 脚本运行 pytest 测试 脚本中的相关行类似于 pytest pytest tests param my param 根据 pytest 文档 运行 pytest 可能会导致六种不同的退出代码 0 5 我的问题是如
  • PHP 数组插入无法按预期工作

    我正在尝试插入一些项目 假设nitems 它们都彼此不同 到一个数组 不知何故 最终的数组包括n items 它们都是相同的项目 最后插入的项目 这是我的代码 searchResults data foreach allowSearch a
  • 当应用程序在后台时获取本地通知

    当应用程序在后台时 不会调用 didReceive Local notification 所以我尝试从 didFinishLaunchingWithOptions 获取通知 BOOL application UIApplication ap
  • 使用 ffmpeg 创建视频

    我有 100 张图像 PNG 我想使用这些图像创建一个视频 我为此使用 ffmpeg 库 使用命令行我可以轻松创建视频 但是我如何通过编码来做到这一点呢 任何帮助将不胜感激 pragma GCC diagnostic ignored Wde