ffmpeg视频录制

录制视频的基本步骤是:

1. 初始化ffmpeg的基本对象,并将这些对象关联起来,然后打开文件并写入文件头。

2. 编码视频,并将编码后数据存写到文件中。

3. 写入文件尾,并清理ffmpeg对象。

首先,需要初始化ffmpeg的一些对象,初始化的顺序为:

创建并初始化AVOutputFormat, 基于AVOutputFormat创建并初始化AVFormatContext。

然后查找AVCodec, 基于找到的AVCodec创建并初始化AVCodecContext,打开AVCodec。

然后基于找到的AVCodec创建AVStream。

然后创建并初始化AVIOContext。

其中AVStream, AVCodec, AVCodecContext可能会有两组,一组用来录制音频,一组用来录制视频,如下:

AVOutputFormat和AVFormatContext可以通过avformat_alloc_output_context函数来初始化。

AVCodec通过avcodec_find_encoder函数来查找

AVCodecContext通过avcodec_alloc_context3来分配

AVCodecContext初始化完成后,可以通过avcodec_open2打开编码器

AVStream通过avformat_new_stream来分配

以上对象初始化完成后,需要将codec的信息拷贝到AVFormatContext对象中,以便与将编码器信息存储到文件中,这个操作可以通过avcodec_parameters_from_context操作

最后通过avio_open打开文件并初始化AVIOContext。

最后通过avformat_write_header写入文件头,整个初始化阶段就算是完成了

以下初始化代码供参考:

avformat_alloc_output_context2(&format_context_, nullptr, nullptr, file_path.c_str());if(format_context_ == nullptr){avformat_alloc_output_context2(&format_context_, nullptr, "mpeg", file_path.c_str());}if(format_context_ == nullptr){return false;}AVOutputFormat *output_format = format_context_->oformat;output_format->video_codec = AV_CODEC_ID_H264;AVCodec *codec = avcodec_find_encoder(output_format->video_codec);codec_context_ = avcodec_alloc_context3(codec);codec_context_->codec_id = output_format->video_codec;codec_context_->pix_fmt = AV_PIX_FMT_YUV420P;codec_context_->width = width;codec_context_->height = height;codec_context_->time_base = {1, 1000};codec_context_->gop_size = 12;if (codec_context_->codec_id == AV_CODEC_ID_MPEG2VIDEO){codec_context_->max_b_frames = 2;}if (codec_context_->codec_id == AV_CODEC_ID_MPEG1VIDEO){codec_context_->mb_decision = 2;}if (output_format->flags & AVFMT_GLOBALHEADER)codec_context_->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;int ret = avcodec_open2(codec_context_, codec, nullptr);if(ret != 0){return false;}video_stream_ = avformat_new_stream(format_context_, codec);if(video_stream_ == nullptr){return false;}ret = avcodec_parameters_from_context(video_stream_->codecpar, codec_context_);if(ret != 0){return false;}ret = avio_open(&format_context_->pb, file_path.c_str(), AVIO_FLAG_WRITE);if(ret != 0){return false;}ret = avformat_write_header(format_context_, nullptr);if(ret != 0){return false;}

 注意,有些编码器只支持一些固定的帧率,对于这样的编码器,AVCodecContext中的time_base是不能随便设置的,当写文件头失败时,可以检查一下这一点

初始化完成后,就可以进行视频编码录制了,跟初始化相比,编码录制的过程要简单的多,核心函数就三个:

avcodec_send_frame进行视频编码

avcodec_receive_packet用于获取编码后的数据

av_write_frame用于将编码后的数据写入文件

以下代码供参考:

av_image_fill_arrays(src_frame_->data, src_frame_->linesize, data,AV_PIX_FMT_RGB24, src_frame_->width, src_frame_->height, 1);sws_scale(sws_context_, src_frame_->data, src_frame_->linesize, 0, src_frame_->height,dst_frame_->data, dst_frame_->linesize);auto now_time = std::chrono::steady_clock::now();dst_frame_->pts = std::chrono::duration_cast<std::chrono::milliseconds>(now_time - start_time_point_).count();int ret = avcodec_send_frame(codec_context_, dst_frame_);if(ret == 0){AVPacket packet;av_init_packet(&packet);ret = avcodec_receive_packet(codec_context_, &packet);if(ret == 0){av_packet_rescale_ts(&packet, codec_context_->time_base, video_stream_->time_base);av_write_frame(format_context_, &packet);}av_packet_unref(&packet);}

这里的第16行注意一下,将编码后的数据写入文件之前,一定要进行时间转换,否则播放视频时会出现视频播放速度太快的问题

最后就是结束录制了,这个过程就不用多说了,看代码:

if(format_context_ != nullptr){av_write_trailer(format_context_);}if(sws_context_ != nullptr){sws_freeContext(sws_context_);sws_context_ = nullptr;}if(codec_context_ != nullptr){avcodec_close(codec_context_);avcodec_free_context(&codec_context_);}if(format_context_ != nullptr){avio_close(format_context_->pb);avformat_free_context(format_context_);format_context_ = nullptr;}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/143201.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

html 视频录制插件,网页视频录制插件工具(浏览器插件 Recorder)

网页视频录制插件工具(浏览器插件 Recorder)Loom Video Recorder是一款视频录制工具扩展插件&#xff0c;可以一键录制浏览器的单个标签页,&#xff0c;也支持摄像头录制&#xff0c;能够将录制的视频内容下载道本地&#xff0c;有需要的用户不要错过了&#xff0c;欢迎下载使用…

如何录制一个高品质的网页直播视频,录制在线直播视频的快速教程

怎么录制网页上的直播视频&#xff1f;怎么录制网页上正在播放的视频&#xff1f;怎么把别人在线直播的视频快速录制下来&#xff1f; 今天就教大家用超级捕快来快速录制一个高品质的网页直播视频&#xff0c;高清无损&#xff0c;没有水印。不仅能录制在线直播视频&#xff0…

浏览器怎么录制网页视频?3种网页视频录制方法

我们每天都会在浏览器上观看大量的视频&#xff0c;尤其是在爱奇艺、腾讯、哔哩哔哩等网页上。有时候就会观看到一些精彩的视频画面&#xff0c;就想要将这些画面给下载。 那怎么把网页视频录制下来&#xff1f;今天本文就给大家分享3种有效的网页视频录制方法&#xff0c;有需…

k8s进阶5——AppArmor、Seccomp、ImagePolicyWebhook

文章目录 一、AppArmor限制容器对资源访问1.1 实现步骤1.1.1 定义策略1.1.2 加载策略1.1.3 引用策略 2.2 案例 二、Seccomp 限制容器进程系统调用案例一&#xff1a;使用自定义策略案例二&#xff1a;使用容器运行时默认策略 三、动态准入控制Webhook3.1 ImagePolicyWebhook控制…

数组如何转对象

最近做项目的时候需要把拿到的数组转为对象使用 let arr [{id:1,value:正式},{id:2,value:非正式}]//首先定义一个空对象let obj{}//循环遍历数组arr.forEach(item>{//把id作为对象的键 把value作为对象的值值obj[item.id]item.value})console.log(obj);运行结果如下 这样…

对象转为数组

对象转成数组 在开发中&#xff0c;前端处理数据&#xff0c;很多时候都会用到把对象转成数组&#xff0c;话不多说&#xff0c;咱们直接上代码 // 对象转数组&#xff0c;想要转成什么字段根据需求 function fmObjToArr (data) {let arr []for (let key in data) {arr.push…

js数组对象转对象

将数组对象的数据转换为普通对象键值对key:value的形式 let arr [{id:1,employeeNo:110,name:张三},{id:2,employeeNo:111,name:李四},{id:3,employeeNo:112,name:王五},{id:4,employeeNo:113,name:章雨},{id:5,employeeNo:114,name:小红}, ] let newObj {} arr.map(item >…

JS对象转数组

一、JS对象转数组方法如下(不考虑for相关遍历): 1.[...res] 2.Array.from(res) 3.Object.values(res) 4. Array.prototype.slice.call(res) let obj {name:李四, age:22, gender:男} //可枚举 let obj2 {0:李四, 1:22, 2:男, length:3} //可枚举 伪数组 let set new Set([…

3种JavaScript 对象转数组的方法

来源 | https://www.fly63.com 我们在项目开发的时候&#xff0c;有时需要将js对象转换为数组&#xff0c;下面小编给大家具体演示一下怎么转换&#xff0c;主要是介绍一些常用、简洁的转换方法。 比如JavaScript对象如下&#xff1a; let obj {name: 前端,url: https://www.w…

对象数据如何转化成数组

文章目录 前言一、后端给的数据二、如何转换三、最终结果 前言 项目中后端给的数据有时候不可能完全符合前端的数据要求&#xff0c;比如element-uivue项目组合中&#xff0c;下拉框数据是数组的形式。然而后端同事给的确是对象数据&#xff0c;当然你可以和后端协商改成你想要…

json对象转对象数组

对象的两种取值方式 let obj {name: wan}; console.log(obj.name); //wan这是最普通的一种方式&#xff0c;还有一种方式我们用的不太多&#xff0c;就是使用[]包住属性名取值 let obj {name: wan}; console.log(obj[name]); //wan将对象转化为数组 let obj {未完成:5, 已…

将数组转换为对象

本文翻译自&#xff1a;Convert Array to Object What is the best way to convert: 转换的最佳方式是什么&#xff1a; [a,b,c]to: 至&#xff1a; {0: a,1: b,2: c }#1楼 参考&#xff1a;https://stackoom.com/question/Hghl/将数组转换为对象 #2楼 Quick and dirty #2…

js把对象转换成数组

1.把类似数组的对象转换成数组 【1】什么是类似数组的对象 比如&#xff1a; let arrayLike {0:"z",1:"y",2:"k",length:3 }; 本质是有length属性&#xff0c;可以类似数组的获取元素的方式arrayLike[0]、arrayLike[1]去获取元素&#xff0…

js数组转对象

js数组转对象 1.js var list {}; var arr ["123","456","789"]; for (var key in arr) {list[key] arr[key]; } console.log(list); 效果&#xff1a;

JS 中的类数组对象如何转换为数组?

大家好&#xff0c;我是前端西瓜哥&#xff0c;今天说一下 JS 的类数组对象是什么&#xff0c;以及如何将类数组对象转为数组。 类数组对象是什么&#xff1f; 类数组对象&#xff0c;就是含有 length 属性的对象&#xff0c;但这个对象不是数组。 通常来说还会有 0 &#x…

js中对象转数组

今天睡前看到小组群里贴了这么一张图&#xff0c;印象中曾经面试的时候好像也是遇到过&#xff0c;对于大佬们来说这肯定是很基础的一道题&#xff0c;在此分享给正在学习前端和正在面试的小伙伴们。 这里我用fo……in……实现了两种取值方式的改变 let obj {json:0,production…

(十六)创建Lua脚本模板

Unity里能创建 c#脚本模板&#xff0c;但是如果我想创建Lua脚本模板怎么办呢&#xff1f;拓展一下编辑器吧。 设置一下Lua脚本的模板地址 &#xff1a; Assets/Editor/Lua/Template/lua.lua using UnityEngine; using UnityEditor; using System; using System.IO; using Sys…

Unity(二十):创建自定义脚本模板

编辑器内部自定义脚本存储位置展示 创建自己的自定义脚本 using System.Collections.Generic; using System.IO; using System.Linq; using System.Text.RegularExpressions; using UnityEditor; using UnityEditor.ProjectWindowCallback; using UnityEngine;internal class C…

修改Visual Studio中C#中的默认脚本模板方法

目录 一、修改后的效果 二、修改Visual Studio中C#的默认脚本步骤 三、验证修改模板是否成功 一、修改后的效果 二、修改Visual Studio中C#的默认脚本步骤 ①如果按照Visual Studio的默认安装路径安装该IDE,则路径为&#xff1a; C:\Program Files (x86)\Microsoft Visual …

Unity 添加,修改默认创建脚本模板

Unity 默认创建的脚本可以添加也可以修改&#xff0c;不需要修改Editor。 一、找到模板目录 \Editor\Data\Resources\ScriptTemplates 二、如果要修改模板&#xff0c;直接打开修改就可以了&#xff0c;每个模板都是可以修改的。 修改默认unity创建的脚本&#xff1a; 三、如…