视频采集到录制 - MP4生成

news2024/12/23 2:02:18

录制最终格式是MP4,视频流是采用H264编码流,音频是aac编码流

最终需要将两个流合并到一个文件里

采用的方案,是通过mp4v2的库,进行合并

原理很简单:

先创建文件,输入编码参数

        需要创建视频流初始

        也需要创建音频流初始化

//创建MP4文件

mFileHandle = CreateMP4File(file,90000);   记住handle

//创建音频通道

MP4TrackId audio = MP4AddAudioTrack(mFileHandle, VOICE_RATE, 1024, MP4_MPEG4_AUDIO_TYPE);

//创建视频通道

mVideoId = MP4AddH264VideoTrack( mFileHandle,
                mTimeScale,
                mTimeScale / mFrameRate,
                mWidth,
                mHeight,
                nalu.data[1], /* sps[1] AVCProfileIndication */
                nalu.data[2], /* sps[2] profile_compat */
                nalu.data[3], /* sps[3] AVCLevelIndication */
                3);  

然后按每帧内容存储至文件

看似简单,实际也有很多

1. 音频初始化参数设置

GetDecoderSpecificInfo

注意,他的参数含义,网上很多例子都是44.1k,因此,而参数里如果不细究,这个就会被忽略

auto config = GetDecoderSpecificInfo(2, 3, 2);

/*

参数1:AAC_LC-2;  这个表示音频编码

参数2:   48000-3,44100-4;

参数3:   2 channels : front - left, front - right

*/

/*添加aac音频*/
        MP4TrackId audio = MP4AddAudioTrack(mFileHandle, VOICE_RATE, 1024, MP4_MPEG4_AUDIO_TYPE);
        if (audio == MP4_INVALID_TRACK_ID)
        {           
            errorf("add audio track failed.\n");
            return false;
        }

        mVoiceId = audio;
        MP4SetAudioProfileLevel(mFileHandle, 0x2);

        /*P1:AAC_LC-2; P2:48000-3,44100-4; P3:2 channels : front - left, front - right*/
        auto config = GetDecoderSpecificInfo(2, 3, 2);
        if(!MP4SetTrackESConfiguration(mFileHandle, audio, (uint8_t*) &config, 2))
        {
            errorf("set audio config failed=2 4 2\n");
        }

2. 视频初始化

        视频编码库编码之后,会产生不同帧,需要解析nalu,不能直接存储

        收到sps帧,需要对视频通道进行初始化

mVideoId = MP4AddH264VideoTrack( mFileHandle,
                mTimeScale,
                mTimeScale / mFrameRate,
                mWidth,
                mHeight,
                nalu.data[1], /* sps[1] AVCProfileIndication */
                nalu.data[2], /* sps[2] profile_compat */
                nalu.data[3], /* sps[3] AVCLevelIndication */
                3);           /* 4 bytes length before each NAL unit */


            if (mVideoId == MP4_INVALID_TRACK_ID)
            {
                errorf("add video track failed.\n");
                return 0;
            }

            MP4SetVideoProfileLevel(mFileHandle, 0x7f); /*  main Profile @ Level 4 */
            MP4AddH264SequenceParameterSet(mFileHandle,mVideoId,nalu.data+4,nalu.size);

        收到pps帧,需要设置参数

        

MP4AddH264PictureParameterSet(mFileHandle,mVideoId,nalu.data+4,nalu.size);

另外需要注意是同步帧信息

3. 时间戳概念

        往往新手会忘记时间戳,但这个是神器,必须好好理解

        比如说:视频设置是25帧/秒,如果实际采集只有20帧,或者在变化(一会20,一会25)类似这样。如果不设置时间戳,那么回放的时候会很奇怪,视频一会快一会慢(当然相差不大,裸眼很难分辨出来),但回放时间很真实,例如明明录制了30分钟,但实际回放的时候,只有29分钟。

        

        因此要设置时间戳,时间戳的原点是创建通道的,后面每写入一帧数据,带入时间戳(相对第一个点的时间偏移)

        音频也是

        音频跟视频是分开两个通道的,因此,时间戳也是分开累计,同理,视频跟音频同步,也是基于时间戳!!

        注意第5参数

if(!MP4WriteSample(mFileHandle, mVideoId, nalu.data, nalu.size+4, (now - mVideoTick) * 90, 0, isSync))
uint64_t timeStemp = (tickTime - mVoiceTick) * VOICE_RATE_STAMP;
    mVoiceTick = tickTime;

  
    if(!MP4WriteSample(mFileHandle, mVoiceId, buf, size, timeStemp, 0, 1))

 

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

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

相关文章

制造业在数字化时代如何应对挑战和机遇?

随着数字化时代的到来,制造业不可避免地会受到一些对应的挑战和机遇。以下是一些关键部分: 数字化转型:制造商已经采用数字技术来转变他们的运营。包括采用高级分析、自动化、人工智能 (AI) 和物联网 (IoT)。这些技术可以提高生产力、质量控制…

2.项目数仓、项目工具

项目数仓 数仓(Data Warehouse)是指用于存储和管理企业数据的一种大型数据库系统,以支持企业的决策分析活动。它采用了ETL(抽取、转化、加载)等技术来集成和清洗数据,并提供了灵活的查询和报表功能,使得分析师和决策者可以更好地理解企业的业务情况和趋势。 项目工…

基于三相坐标系状态方程的感应电动机起动动态计算(Matlab代码实现)

💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…

DataGrip使用技巧总结

🍓 简介:java系列技术分享(👉持续更新中…🔥) 🍓 初衷:一起学习、一起进步、坚持不懈 🍓 如果文章内容有误与您的想法不一致,欢迎大家在评论区指正🙏 🍓 希望这篇文章对你有所帮助,欢…

照片怎么拼图?简单好用的拼图方法分享

照片的拼接不仅能够让我们将多张照片合成一张大图,还能够发挥我们的想象和创意,例如,我们可以将不同的照片拼接在一起,创造出一个全新的场景,或者将同一个场景的不同角度的照片拼接在一起,制作出一个完整的…

一个网站建设公司如何保障提供优质的服务

网站建设公司提供的服务是否优质,直接影响到客户的口碑,也会影响到公司的口碑。 一个好的网站建设公司,不仅会提供优质的服务,还会有专业的技术人员对客户进行跟踪服务。这是一项重要的工作,需要一个网站建设公司不断…

《神奇的连接组》读后

人类大脑被戏称为“三磅的宇宙”,或许可以从科学上解释关于“意识”的问题,大脑的神经科学可能是人类科学的最终前沿。 任何真正先进的科技,看起来都与魔法无异。 要解释大脑如何运转,单凭基因无法解释大脑为什么这样工作&#xf…

Java——Java易错选择题复习(2)(计算机网络)

1. 下面关于源端口地址和目标端口地址的描述中,正确的是( ) A. 在TCP/UDP传输段中,源端口地址和目的端口地址是不能相同的 B. 在TCP/UDP传输段中,源端口地址和目的端口地址必须是相同的 C. 在TCP/UDP传输段中&#xff…

chatgpt赋能python:Python声音处理之变声

Python声音处理之变声 随着科技的发展,人们对于声音处理越来越感兴趣。变声技术就是其中的一种,它可以将一个人的声音变成其他的人或动物的声音,非常有趣。 Python作为一种广泛使用的编程语言,可以在声音处理中发挥重要作用。本…

如何在食品行业运用IPD?

食品是我国重要的民生产业之一,是保障和满足人民群众不断增长消费需求的重要支撑。食品指各种供人食用或者饮用的成品和原料以及按照传统既是食品又是药品的物品,包括加工食品,半成品和未加工食品,不包括烟草或只作药品用的物质。…

为数据可视化增添戏剧性

Python 中的视觉叙事:让数据说话的 5 个创新技巧 为数据可视化增添戏剧性 数据可视化 - 这是一个现在经常被抛出的短语。但我们谈论的不仅仅是普通的旧图表和图形。 不 不 不。我们谈论的是讲故事。我们正在谈论将这些行和列的数字变成令人着迷的叙述。 现在是我们从…

Elasticsearch:数据是如何被写入的?

在我之前的文章 “Elasticsearch:索引数据是如何完成的”,我详述了如何索引 Elasticsearch 的数据的。在今天的文章中,我将从另外一个视角来诠释如何写入数据到 Elasticsearch。更多关于 Elasticsearch 数据操作,请阅读文章 “Ela…

PowerShell install 一键部署postgres15

postgres 前言 PostgreSQL 是一个功能强大的开源对象关系数据库系统,拥有超过 35 年的积极开发经验 这为其赢得了可靠性、功能稳健性和性能的良好声誉。 通过官方文档可以找到大量描述如何安装和使用 PostgreSQL 的信息。 开源社区提供了许多有用的地方来熟悉Postg…

08 【生命周期 组件】

1. 生命周期 1.1 引出生命周期 生命周期 又名生命周期回调函数,生命周期函数、生命周期钩子是什么,Vue在关键时刻帮我们调用的一些特殊名称函数生命周期函数的名字不可更改,但函数的具体内容是根据程序员需求编写的生命周期函数中的this指向的是vm或组件实例对象 <div i…

贺斌教授团队:多少冥想训练才能提高脑机接口的性能?

冥想训练可以帮助人们学会更好地控制脑机接口。但是一项新的研究发现&#xff0c;单次的冥想练习不足以提高表现。发表在《Frontiers in Human Neuroscience》的一项研究结果表明&#xff0c;人们需要更长时间的冥想才能体验到明显的改善。 # 脑机接口性能如何提高&#xff1f;…

kafka 集群是如何选择 leader,你知道吗?

前言 kafka集群是由多个broker节点组成&#xff0c;这里面包含了许多的知识点&#xff0c;以下的这些问题你都知道吗? 你知道topic的分区leader是怎么选举的吗&#xff1f; 你知道zookeeper中存储了kafka的什么信息吗&#xff1f;起到什么做呢&#xff1f; 你知道kafka消息…

基于matlab地形可视化仿真

一、前言 此示例说明了将常规可用的数字高程模型转换为 X3D 格式以用于虚拟现实场景的可能性。 作为地形数据源&#xff0c;已使用南旧金山 DEM 模型。场景中包含一个简单的预制波音 747 模型&#xff0c;以展示从多个来源即时创建虚拟场景的技术。 此示例需要映射工具箱。 二、…

高通全面进攻智能汽车「路径」

“统一技术路线图”&#xff0c;被高通技术公司高级副总裁兼汽车业务总经理Nakul Duggal着重提及。 5月26日&#xff0c;高通在苏州举办汽车技术与合作峰会&#xff0c;Nakul Duggal在峰会上坦言&#xff0c;“我们在所有业务领域、所有产品开发中都遵循‘统一技术路线图’&am…

【owt】WebrtcNode, publish-sdp offer 流程(2)

流程图 创建MediaStream&#xff0c; MediaStream一方面作为从客户端接收到媒体数据&#xff0c;另外一方面做为视频源&#xff1b;创建VideoFrameConstructor&#xff0c;VideoFrameConstructor 把sink 注册到MediaStream&#xff0c;这样MediaStream&#xff08;继承了MediaS…

运维小白必学篇之基础篇第七集:磁盘管理实验

磁盘管理实验 实验作业&#xff1a; 1、添加1块磁盘&#xff0c;并查看&#xff08;lsblk&#xff09; 2、使用MBR分区表的格式对添加的磁盘划分分区&#xff0c;完成以下操作&#xff1a; 1、创建3个主分区&#xff0c;每个分区大小为2个GB 2、创建扩展分区&#xff0c;将剩…