- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试编写一个程序来生成要通过 ffmpeg/libav 编码到具有单个 h264 流的 mp4 文件的帧。我找到了这两个示例,并试图将它们合并在一起以制作我想要的:[ video transcoder ] [ raw MPEG1 encoder ]
我已经能够获得视频输出(绿色圆圈改变大小),但无论我如何设置帧的 PTS 值或 time_base
我在 AVCodecContext
中指定或 AVStream
,我得到的帧速率约为 7000-15000 而不是 60,导致视频文件持续 70 毫秒而不是 1000 帧/60 fps = 166 秒。每次我更改一些代码时,帧速率都会发生一点变化,就好像它正在从未初始化的内存中读取一样。 StackOverflow 上对此类问题的其他引用似乎与错误设置的 PTS 值有关;但是,我尝试打印出我能找到的所有 PTS、DTS 和时基值,它们看起来都很正常。这是我的概念验证代码(为了清楚起见,删除了捕获 libav 调用周围的东西的错误):
#include <iostream>
#include <opencv2/opencv.hpp>
#include <math.h>
extern "C" {
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavutil/opt.h>
#include <libavutil/timestamp.h>
}
using namespace cv;
int main(int argc, char *argv[]) {
const char *filename = "testvideo.mp4";
AVFormatContext *avfc;
avformat_alloc_output_context2(&avfc, NULL, NULL, filename);
AVStream *stream = avformat_new_stream(avfc, NULL);
AVCodec *h264 = avcodec_find_encoder(AV_CODEC_ID_H264);
AVCodecContext *avcc = avcodec_alloc_context3(h264);
av_opt_set(avcc->priv_data, "preset", "fast", 0);
av_opt_set(avcc->priv_data, "crf", "20", 0);
avcc->thread_count = 1;
avcc->width = 1920;
avcc->height = 1080;
avcc->pix_fmt = AV_PIX_FMT_YUV420P;
avcc->time_base = av_make_q(1, 60);
stream->time_base = avcc->time_base;
if(avfc->oformat->flags & AVFMT_GLOBALHEADER)
avcc->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
avcodec_open2(avcc, h264, NULL);
avcodec_parameters_from_context(stream->codecpar, avcc);
avio_open(&avfc->pb, filename, AVIO_FLAG_WRITE);
avformat_write_header(avfc, NULL);
Mat frame, nothing = Mat::zeros(1080, 1920, CV_8UC1);
AVFrame *avf = av_frame_alloc();
AVPacket *avp = av_packet_alloc();
int ret;
avf->format = AV_PIX_FMT_YUV420P;
avf->width = 1920;
avf->height = 1080;
avf->linesize[0] = 1920;
avf->linesize[1] = 1920;
avf->linesize[2] = 1920;
for(int x=0; x<1000; x++) {
frame = Mat::zeros(1080, 1920, CV_8UC1);
circle(frame, Point(1920/2, 1080/2), 250*(sin(2*M_PI*x/1000*3)+1.01), Scalar(255), 10);
avf->data[0] = frame.data;
avf->data[1] = nothing.data;
avf->data[2] = nothing.data;
avf->pts = x;
ret = 0;
do {
if(ret == AVERROR(EAGAIN)) {
av_packet_unref(avp);
ret = avcodec_receive_packet(avcc, avp);
if(ret) break; // deal with error
av_write_frame(avfc, avp);
} //else if(ret) deal with error
ret = avcodec_send_frame(avcc, avf);
} while(ret);
}
// flush the rest of the packets
avcodec_send_frame(avcc, NULL);
do {
av_packet_unref(avp);
ret = avcodec_receive_packet(avcc, avp);
if(!ret)
av_write_frame(avfc, avp);
} while(!ret);
av_frame_free(&avf);
av_packet_free(&avp);
av_write_trailer(avfc);
avformat_close_input(&avfc);
avformat_free_context(avfc);
avcodec_free_context(&avcc);
return 0;
}
这是
ffprobe
的输出在输出视频文件上运行
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'testvideo.mp4':
Metadata:
major_brand : isom
minor_version : 512
compatible_brands: isomiso2avc1mp41
encoder : Lavf58.76.100
Duration: 00:00:00.07, start: 0.000000, bitrate: 115192 kb/s
Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p, 1920x1080, 115389 kb/s, 15375.38 fps, 15360 tbr, 15360 tbn, 120 tbc (default)
Metadata:
handler_name : VideoHandler
vendor_id : [0][0][0][0]
什么可能导致我的帧速率如此之高?提前感谢您的帮助。
最佳答案
由于您未能设置 数据包持续时间 ,因此您获得了高帧率。
time_base
设置为更高分辨率(如 1/60000),如 here 所述: avcc->time_base = av_make_q(1, 60000);
avp->duration
描述为 here : AVRational avg_frame_rate = av_make_q(60, 1); //60 fps
avp->duration = avcc->time_base.den / avcc->time_base.num / avg_frame_rate.num * avg_frame_rate.den; //avp->duration = 1000 (60000/60)
并相应地设置 pts
。#include <iostream>
#include <opencv2/opencv.hpp>
#include <math.h>
extern "C" {
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavutil/opt.h>
#include <libavutil/timestamp.h>
}
using namespace cv;
int main(int argc, char* argv[]) {
const char* filename = "testvideo.mp4";
AVFormatContext* avfc;
avformat_alloc_output_context2(&avfc, NULL, NULL, filename);
AVStream* stream = avformat_new_stream(avfc, NULL);
AVCodec* h264 = avcodec_find_encoder(AV_CODEC_ID_H264);
AVCodecContext* avcc = avcodec_alloc_context3(h264);
av_opt_set(avcc->priv_data, "preset", "fast", 0);
av_opt_set(avcc->priv_data, "crf", "20", 0);
avcc->thread_count = 1;
avcc->width = 1920;
avcc->height = 1080;
avcc->pix_fmt = AV_PIX_FMT_YUV420P;
//Sey the time_base to higher resolution like 1/60000
avcc->time_base = av_make_q(1, 60000); //avcc->time_base = av_make_q(1, 60);
stream->time_base = avcc->time_base;
if (avfc->oformat->flags & AVFMT_GLOBALHEADER)
avcc->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
avcodec_open2(avcc, h264, NULL);
avcodec_parameters_from_context(stream->codecpar, avcc);
avio_open(&avfc->pb, filename, AVIO_FLAG_WRITE);
avformat_write_header(avfc, NULL);
Mat frame, nothing = Mat::zeros(1080, 1920, CV_8UC1);
AVFrame* avf = av_frame_alloc();
AVPacket* avp = av_packet_alloc();
int ret;
avf->format = AV_PIX_FMT_YUV420P;
avf->width = 1920;
avf->height = 1080;
avf->linesize[0] = 1920;
avf->linesize[1] = 1920;
avf->linesize[2] = 1920;
for (int x = 0; x < 1000; x++) {
frame = Mat::zeros(1080, 1920, CV_8UC1);
circle(frame, Point(1920 / 2, 1080 / 2), (int)(250.0 * (sin(2 * M_PI * x / 1000 * 3) + 1.01)), Scalar(255), 10);
AVRational avg_frame_rate = av_make_q(60, 1); //60 fps
int64_t avp_duration = avcc->time_base.den / avcc->time_base.num / avg_frame_rate.num * avg_frame_rate.den;
avf->data[0] = frame.data;
avf->data[1] = nothing.data;
avf->data[2] = nothing.data;
avf->pts = (int64_t)x * avp_duration; // avp->duration = 1000
ret = 0;
do {
if (ret == AVERROR(EAGAIN)) {
av_packet_unref(avp);
ret = avcodec_receive_packet(avcc, avp);
if (ret) break; // deal with error
////////////////////////////////////////////////////////////////
//avp->duration was zero.
avp->duration = avp_duration; //avp->duration = 1000 (60000/60)
//avp->pts = (int64_t)x * avp->duration;
////////////////////////////////////////////////////////////////
av_write_frame(avfc, avp);
} //else if(ret) deal with error
ret = avcodec_send_frame(avcc, avf);
} while (ret);
}
// flush the rest of the packets
avcodec_send_frame(avcc, NULL);
do {
av_packet_unref(avp);
ret = avcodec_receive_packet(avcc, avp);
if (!ret)
av_write_frame(avfc, avp);
} while (!ret);
av_frame_free(&avf);
av_packet_free(&avp);
av_write_trailer(avfc);
avformat_close_input(&avfc);
avformat_free_context(avfc);
avcodec_free_context(&avcc);
return 0;
}
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'testvideo.mp4':
Metadata:
major_brand : isom
minor_version : 512
compatible_brands: isomiso2avc1mp41
encoder : Lavf58.76.100
Duration: 00:00:16.65, start: 0.000000, bitrate: 456 kb/s
Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p, 1920x1080, 450 kb/s, 60.06 fps, 60 tbr, 60k tbn, 120k tbc (default)
Metadata:
handler_name : VideoHandler
vendor_id : [0][0][0][0]
MB rate (734400000) > level limit (16711680)
我没有修复。 关于c++ - libav 生成具有极高帧速率的 MP4 文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70060148/
来自Linux背景。我只是想知道在 OSX 上安装 avprobe 的最佳方法是什么? 我尝试安装 libav:http://libav.org/download.html但这似乎使用了avconf。
如何在FFmpeg C API中编码之前为帧计算正确的PTS值? 为了进行编码,我使用了avcodec_encode_video2函数,然后通过av_interleaved_write_frame编写
使用 libav 保存视频中的帧。 问题是,如果你多次调用 decode 函数,然后调用 2nd,然后就没有正确处理。 第一次这样的结论(一切正常): [swscaler @ 0x8b48510]No
我正在尝试制作一个简单的 av 播放器,在某些情况下,我可以正确获取如下值: checking /media/timecapsule/Music/02 Baawre.mp3 [mp3 @ 0x7f06
我在OS X Mavericks上没有安装libav的运气。我已经尝试了一切。 我正在遵循此指南:http://earthwithsun.com/questions/568464/install-la
尝试使用 ffmpeg 打开网络摄像头(ffplay -f video4linux2/dev/video0 有效 pFormatCtx = NULL; av_register_all(
我使用下面的命令来转换文件 ./avconv -i inputFile -vcodec libx264 -trellis 2 -crf 23 -tune psnr -vf Crop='trunc(iw
我试图通过使用代码将 MP2 文件转换为原始 PCM 来获得与 ffmpeg/avconv 相同的输出。我使用了 the tutorial included in the FFmpeg/Libav d
我正在关注 ffmpeg 文档中的音频编码示例:https://www.ffmpeg.org/doxygen/0.6/api-example_8c-source.html 但我想解码 .wav 文件,
我正在尝试使用 libav(ffmpeg) 创建带有 MJPEG 视频负载的 RTP 流示例代码非常简单,适用于 MPEG1我看到 MJPEG 中的编码有效,但是当我需要发送 mjpeg 时帧 RTP
有没有办法使用 libav/avconv 来复制 FFMPEG 中瓦片过滤器的效果? 我正在尝试为每十秒的视频输入创建一个从左到右的图像 strip 。 我的计划是首先生成图像,然后创建图像条。最好我
我正在尝试使用 libav 在我的应用程序中删除视频的某些部分,例如在长度为 00:08:00 的视频中,我尝试删除帧 100-250 和 400-500(仅作为示例)。 我写了这段代码来复制 AVP
我有一个能够同时生成 5 个 mpeg 传输流的程序。每个流都有自己的上下文,并在独立的线程中完成。当只有一个流处于事件状态时,一切都很好。一旦我激活另一个流,我的帧速率就会大大下降。两个流仍然可以正
我有一系列编码数据包、H.264 视频和 AAC 音频。当它们出现时,我正在使用 av_write_frame 将它们写入视频文件。 连续给定以下情况 10秒视频,然后 10 秒的视频和音频,然后 1
我看到了这个答案,Libav (ffmpeg) copying decoded video timestamps to encoder 但我仍然不明白为什么我们需要流时基和编解码器时基。目前我正在尝试
我正在尝试学习使用 libav。我遵循了 dranger.com 上的第一个教程,但有一次我有点困惑。 // Write pixel data for(y=0; ydata[0]+y*pFrame->
我有一个从我的手机以纵向模式拍摄的视频。以下是有关视频的转储信息: Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'video.MOV': Metadata: maj
我有一个带有卡住(热)像素的视频,我想修复它,比如说用相邻像素的平均值替换像素。我在 Ubuntu 上,所以我想使用 libav/ffmpeg,但我真的不知道该怎么做。谁能提供一个简单的解决方案? 最
这个问题在这里已经有了答案: FFMPEG (libx264) "height not divisible by 2" (7 个回答) 5年前关闭。 我需要批量处理一堆视频以将它们的高度缩放到 240
我目前正在使用 libav 将视频的音频流提取到原始 PCM 文件中。 此代码适用于 mp3,但当我尝试使用 mp4 视频时,Audacity 上导入的原始格式显示奇怪的 0 到 -1 之间的规则下降
我是一名优秀的程序员,十分优秀!