使用ffmpeg创建视频
Create video using ffmpeg
我有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 encodingn");
// find the mpeg1 video encoder
codec = avcodec_find_encoder((CodecID) codec_id);
if (!codec) {
fprintf(stderr, "codec not foundn");
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 codecn");
exit(1);
}
f = fopen(filename, "wb");
if (!f) {
fprintf(stderr, "could not open %sn", 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;
}
- 每次搜索时我都会得到类似的代码。但我不理解hot用它来创建图像视频
之所以一次又一次地出现这种情况,是因为您使用encoding_example.c作为引用。请不要那样做。这个例子中最根本的错误是它没有教会你编解码器和容器之间的区别。事实上,它完全忽略了容器。
什么是编解码器编解码器是一种压缩媒体类型的方法。例如,H264将压缩原始视频。想象一个1080p的视频帧,它通常是具有4:2:0色度子采样的YUV格式。原始,每帧1080*11920*3/2字节,即~3MB/f。对于60fps,这是180MB/秒,或1.44吉比特/秒(gbps)。这是很多数据,所以我们压缩它。在这个分辨率下,对于现代编解码器,如H264、HEVC或VP9,你可以以几兆比特/秒(mbps)的速度获得相当高的质量。对于音频,像AAC或Opus这样的编解码器很受欢迎。
什么是容器容器获取视频或音频(或字幕)数据包(压缩或未压缩),并将它们交错存储在单个输出文件中。因此,与其得到一个视频文件和一个音频文件,不如得到一个交织两者数据包的文件。这允许有效的搜索和索引,通常还允许添加元数据存储("作者"、"标题")等。流行容器的示例有MOV、MP4(实际上只是MOV)、AVI、Ogg、Matroska或WebM(实际上只是Matroska)。
(如果需要,您可以将仅视频数据存储在文件中。对于H264,这被称为"annelb"原始H264。这实际上就是你在上面所做的。那为什么它不起作用呢?好吧,您忽略了SPS和PPS之类的"标头"数据包。这些都在avctx->extradata中,需要在第一个视频包之前写入。使用容器会帮你解决这个问题,但你没有,所以它不起作用。)
如何在FFmpeg中使用容器?例如,请参阅本文,特别是调用avformat_write_*()
(基本上是任何听起来像输出的函数)等函数的部分。我很乐意回答更具体的问题,但我认为上面的帖子应该会为你消除大部分困惑。
- 使用 OpenCV C++ 每 1 分钟创建新的视频文件
- 创建可用的H.264视频文件
- OPENCV从Yuyv Pixelformat视频框架创建YUV420或灰度垫子对象
- 使用最新的 ffmpeg API (2017) 创建视频
- 使用C++创建带有“自定义”捕获器的WebRTC视频轨道
- 如何使用AvConv创建灰度视频
- 如何使用avcodec从OpenCV::Mat类型的jpeg图像创建视频
- 开放框架,从两个视频采集卡创建视频纹理
- 使用 QT 创建器在 c++ 中播放视频
- 使用ffmpeg创建视频
- Qml视频创建从C++的图像流
- 从多个视频部分创建单个视频文件
- 从帧创建视频
- C ++从多个视频文件创建1个视频
- 在由 createdesktop() 创建的新桌面中播放视频
- 如何在Qt创建器中的Qt小部件应用程序中播放本地视频
- 使用QT Creator-C++中的QPixmap序列创建视频文件
- DirectShow过滤器图形使用WMASFWriter创建视频太短
- 如何从磁盘加载Jpeg图像并创建视频文件?Avi等),而无需在c++中使用opencv
- Qt创建视频/AVI文件从小部件