解决AAC音频编码时间戳的计算问题
1.主题
音频是流式数据,并不像视频一样有P帧和B帧的概念。就像砌墙一样,咔咔往上摞就行了。一般来说,AAC编码中生成文件这一步,如果使用的是OutputStream流写入文件的话,就完全不需要计算时间。但在音视频同步或者使用Android自带的MediaMuxer来生成音频文件时,就需要计算音频帧的时间戳。
2.参考
本文所涉及到的计算方法和API,为在Android环境下。使用AudioRecord音频录制,MediaCodeC编码AAC格式音频,同时使用MediaMuxer封装AAC格式音频文件。
3.方法
AAC编码有两种计算时间戳的方式。第一种:使用PCM的数据量来计算;第二种:计算出AAC编码相应参数配置下,一帧的持续时间,再配合帧数来计算。
4.AAC编码、MediaMuxer生成文件伪代码
MediaCodeC的AAC编码流程不再赘述,这里用伪代码来代替。主要是为了体现在代码何处设置时间戳:
// MediaCodeC获得可用输入队列
index = codeC.dequeueInputBuffer(......)
// 当获取到可用输出队列时,我们将获取的PCM数据填入
inputBuffer = codec.getInputBuffer(index)
// 将PCM数据(ByteArray)填充到InputBuffer
inputBuffer.put(byteAarray——PCM数据)
codec.queueInputBuffer(index, 0, byteArray的size
, presentationTimeUs, 0)
在以上的伪代码中,presentationTimeUs就是需要我们设置时间戳的地方
填充PCM数据后,在得到MediaCodeC输出后,使用MedaMuxer写入数据,生成AAC文件。
path = 输出路径。后缀aac、或者mp4
mediaMuxer= MediaMuxer(path, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4)
mediaMuxer.addTrack(音频轨)
mediaMuxer.start()
// codec拿到可用的输出数据。这些数据就是AAC格式的音频数据
id = codec.dequeueOutputBuffer(bufferInfo, 10000)
if(id >= 0){
outputBuffer = codec.getOutputBuffer(id)
mediaMuxer.writeSamplet(audioTrack, outputBuffer, bufferInfo)
}
需要注意的是:使用MediaMuxer生成AAC音频文件时,不需要添加AAC头信息,直接写入即可。MediaMuxer写入文件时,BufferInfo这个参数就包含了这一帧数据的偏移、以及时间戳等信息。

5.使用PCM的数据量来计算
PCM是没有经过压缩的纯音频数据,我之前写过一篇音频入门的文章初识音频,记录了一些PCM相关的常识问题,感兴趣的可以去看看。PCM作为最原始的音频数据,可以根据大小来计算出时间,先给出公式:
presentationTimeUs = 1000000L * (totalBytes / 2) / sampleRate
这是配置为采样率sampletRate、采样位数为16bit、单声道的PCM文件时间戳计算方式
接下来我们来分析以上公式的计算由来:假设有一段PCM文件,采样率为S,采样位数为n--(一般 采样位数的选择有4bit、8bit、16bit、32bit),声道为单声道。那么在1s内,这段PCM的大小为:
size = S * n * 1,单位为bit
众所周知,1 Byte = 8bit, 1 Short = 16bit。那么单位时间内,PCM的大小为:
以byte为单位 = S * n * 1 / 8
以short为单位 = S * n * 1 / 16
那么根据以上就可得到,配置参数为采样率sampleRate、16bit、声道为1的PCM文件,当传入编码器的总大小达到totalByte时,时间戳的计算方式:
currents (微妙) = totalByte / (sampleRate * 16 * 1 / 8)
= totalByte / 2 / sampleRate * 1000000L
当然如果选择以ShortArray来承载PCM数据的话,那么公式则变为:
currents (微妙) = totalShort / (sampleRate * 16 * 1 / 16)
= totalShort / sampletRate * 1000000L
6.使用AAC帧时间计算
当编码器每输出一次数据,即可视作输出一帧AAC数据。一帧AAC原始数据包括1024个sample,那么AAC音频文件1s内的帧数为:sampleRate / 1024 帧。从而得到一帧AAC的持续时间为:
perFrameTime (微妙) = 1000000L / sampleRate / 1024
原文地址:解决AAC音频编码时间戳的计算问题 - 资料 - 音视频开发中文网 - 构建全国最权威的音视频技术交流分享论坛
★文末名片可以免费领取音视频开发学习资料,内容包括(FFmpeg ,webRTC ,rtmp ,hls ,rtsp ,ffplay ,srs)以及音视频学习路线图等等。
见下方!↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
相关文章:

解决AAC音频编码时间戳的计算问题
1.主题音频是流式数据,并不像视频一样有P帧和B帧的概念。就像砌墙一样,咔咔往上摞就行了。一般来说,AAC编码中生成文件这一步,如果使用的是OutputStream流写入文件的话,就完全不需要计算时间。但在音视频同步或者使用A…...
Android 9.0 添加自定义开机广播
1.概述 在9.0的系统rom定制化开发中,由于系统开机广播接收受限,普通app接收不到这个广播,如果接收这个广播很多应用 感觉要好久收到这个广播, 所以需要自定义开机广播来使用自定义广播开启某些应用,实现自己的功能,接下来就需要分析下开机广播的流程,然后增加自定义广播…...
第四阶段10-添加类别,类别列表mapper层,service层,controller层
63. 添加类别–Mapper层 插入类别数据的功能此前已经完成! 64. 添加类别–Service层 在项目的根包下创建pojo.dto.CategoryAddNewDTO类: Data public class CategoryAddNewDTO implements Serializable {/*** 类别名称*/private String name;/*** 父…...
linux内核启动分析(一)
文章目录1.HEAD1.preserve_boot_args1.1 __inval_dcache_area2.el2_setup3. set_cpu_boot_mode_flag4. __create_page_tables4.1map_memory5. __cpu_setup6. __primary_switch6.1 __enable_mmu6.2 __primary_switched最近工作中经常使用飞腾E2000的开发版,也遇到一些…...

wireshark常见使用操作讲解以及几个故障解决案例分享
(1)网卡选择 对于电脑本身有多个网卡的时候,选择网卡就成为了一个困惑的地方,其实这里很简单,只要把鼠标放在对应的网卡上面就可以看到地址等信息,就容易判断出来了。 (2)过滤器 直…...

利用逻辑分析仪解析串口通讯数据
利用逻辑分析仪解析串口通讯数据🔧采用的是市面上最为广泛使用的USB逻辑分析仪: 📚资料下载: 链接: https://pan.baidu.com/s/1c9lwWDbtJxaJED-kzSbiJg 提取码: 5vnr🔨测试工具为:Logic 2.4.6,也可以使用Pu…...
新整理的前端面试题
pinia和vuex的区别(1)pinia它没有mutation,他只有state,getters,action【同步、异步】使用他来修改state数据(2)pinia他默认也是存入内存中,如果需要使用本地存储,在配置上比vuex麻烦…...

数据仓库-数仓分层
层级 全拼 职责划分 ODS(源数据层) Operational DataStore ODS层存储最原始的数据, 对数据不做任何加工处理; 源数据主要来自业务数据库和日志,这些数据是用户操作业务系统产生,所以叫操作型数据(Operational Data) 。 DWD(…...

【Linux】Linux根文件系统扩容
场景:根文件系统需要至少100GB的剩余空间,但是目前就剩余91GB。因此,我们需要对根文件系统进行扩容。# df -h 文件系统 容量 已用 可用 已用% 挂载点 devtmpfs 3.9G 0 3.9G 0% /dev tmpfs …...

RPC编程:Hessian RPC一个老的RPC框架(一)
RPC编程:Hessian RPC一个老的RPC框架一:Hessian RPC1:Hession RPC一个老的RPC框架2:老,为什么还要研究?3:Hession RPC概念二:Hessian RPC设计思想1:Hession依赖于服务器2…...

逆向 x蜂窝 zzzghostsigh
逆向 x蜂窝 zzzghostsigh 版本 9.3.7 新版本是64位的so charles 抓包 目标字段 zzzghostsigh frida java function hook_xPreAuthencode() {Java.perform(function() {var helper Java.use("com.mfw.tnative.AuthorizeHelper");helper.xPreAuthencode.implemen…...

QML 鼠标事件
作者: 一去、二三里 个人微信号: iwaleon 微信公众号: 高效程序员 QML 中有一些元素本身是不具备交互能力的(例如:Rectangle、Text、Image 等),那么如何通过鼠标来控制它们的行为呢?这里就需要用到 MouseArea 元素了,它继承于 Item 且不可见,通常需要与可见元素结合使…...

极智项目 | 实战pytorch arcface人脸识别
欢迎关注我的公众号 [极智视界],获取我的更多经验分享 大家好,我是极智视界,本文介绍 实战pytorch arcface人脸识别,并提供完整项目源码。 本文介绍的实战arcface人脸识别项目,提供完整的可以一键训练、测试的项目工程…...

【IP技术】ipv4和ipv6是什么?
IPv4和IPv6是两种互联网协议,用于在互联网上标识和寻址设备。IPv4(Internet Protocol version 4)是互联网协议的第四个版本,是当前广泛使用的互联网协议。IPv4地址由32位二进制数构成,通常表示为4个十进制数࿰…...

linux基本功系列之uniq命令实战
文章目录前言一. uniq的命令介绍二. 语法格式及常用选项三. 参考案例3.1 统计行数3.2 对文本进行去重3.3 显示不重复的行3.4 仅显示重复的行,且显示重复的行的所有行3.5 忽略字母大小写总结前言 大家好,又见面了,我是沐风晓月,本…...

六、SpringBoot项目搭建
日志 Java 主流日志工具库 统一接口 什么是 REST? Representational State Transfer——“表现层状态转化”。可以总结为一句话:REST 是所有 Web 应用都应该遵守的架构设计指导原则。面向资源是 REST 最明显的特征,对于同一个资源的一组不…...

【LeetCode】2363. 合并相似的物品
2363. 合并相似的物品 题目描述 给你两个二维整数数组 items1 和 items2 ,表示两个物品集合。每个数组 items 有以下特质: items[i] [valuei, weighti] 其中 valuei 表示第 i 件物品的 价值 ,weighti 表示第 i 件物品的 重量 。items 中每…...

华为OD机试题,用 Java 解【出租车计费】问题
最近更新的博客 华为OD机试题,用 Java 解【停车场车辆统计】问题华为OD机试题,用 Java 解【字符串变换最小字符串】问题华为OD机试题,用 Java 解【计算最大乘积】问题华为OD机试题,用 Java 解【DNA 序列】问题华为OD机试 - 组成最大数(Java) | 机试题算法思路 【2023】使…...

【人脸识别】DDL:数据分布知识蒸馏思想,提升困难样本(遮挡、低分辨率等)识别效果
论文题目:《Improving Face Recognition from Hard Samples via Distribution Distillation Loss》 论文地址:https://arxiv.org/pdf/2002.03662v3.pdf 代码地址:https://github.com/HuangYG123/DDL 1.前言及相关工作 Large facial variatio…...

如何管理好仓库/库房?
仓库管理是企业管理中不可缺少的一部分,事关企业能否正常运行的关键之一,古人有云:“三军未动粮草先行”,一个企业仓库管理做不好,他的生产管理肯定也是做不好的,不是说生产管理人员的管理能力不具备&#…...
day52 ResNet18 CBAM
在深度学习的旅程中,我们不断探索如何提升模型的性能。今天,我将分享我在 ResNet18 模型中插入 CBAM(Convolutional Block Attention Module)模块,并采用分阶段微调策略的实践过程。通过这个过程,我不仅提升…...

DAY 47
三、通道注意力 3.1 通道注意力的定义 # 新增:通道注意力模块(SE模块) class ChannelAttention(nn.Module):"""通道注意力模块(Squeeze-and-Excitation)"""def __init__(self, in_channels, reduction_rat…...

2.Vue编写一个app
1.src中重要的组成 1.1main.ts // 引入createApp用于创建应用 import { createApp } from "vue"; // 引用App根组件 import App from ./App.vue;createApp(App).mount(#app)1.2 App.vue 其中要写三种标签 <template> <!--html--> </template>…...

微信小程序 - 手机震动
一、界面 <button type"primary" bindtap"shortVibrate">短震动</button> <button type"primary" bindtap"longVibrate">长震动</button> 二、js逻辑代码 注:文档 https://developers.weixin.qq…...
WEB3全栈开发——面试专业技能点P2智能合约开发(Solidity)
一、Solidity合约开发 下面是 Solidity 合约开发 的概念、代码示例及讲解,适合用作学习或写简历项目背景说明。 🧠 一、概念简介:Solidity 合约开发 Solidity 是一种专门为 以太坊(Ethereum)平台编写智能合约的高级编…...

如何理解 IP 数据报中的 TTL?
目录 前言理解 前言 面试灵魂一问:说说对 IP 数据报中 TTL 的理解?我们都知道,IP 数据报由首部和数据两部分组成,首部又分为两部分:固定部分和可变部分,共占 20 字节,而即将讨论的 TTL 就位于首…...
Java线上CPU飙高问题排查全指南
一、引言 在Java应用的线上运行环境中,CPU飙高是一个常见且棘手的性能问题。当系统出现CPU飙高时,通常会导致应用响应缓慢,甚至服务不可用,严重影响用户体验和业务运行。因此,掌握一套科学有效的CPU飙高问题排查方法&…...
React---day11
14.4 react-redux第三方库 提供connect、thunk之类的函数 以获取一个banner数据为例子 store: 我们在使用异步的时候理应是要使用中间件的,但是configureStore 已经自动集成了 redux-thunk,注意action里面要返回函数 import { configureS…...

GitFlow 工作模式(详解)
今天再学项目的过程中遇到使用gitflow模式管理代码,因此进行学习并且发布关于gitflow的一些思考 Git与GitFlow模式 我们在写代码的时候通常会进行网上保存,无论是github还是gittee,都是一种基于git去保存代码的形式,这样保存代码…...

在Mathematica中实现Newton-Raphson迭代的收敛时间算法(一般三次多项式)
考察一般的三次多项式,以r为参数: p[z_, r_] : z^3 (r - 1) z - r; roots[r_] : z /. Solve[p[z, r] 0, z]; 此多项式的根为: 尽管看起来这个多项式是特殊的,其实一般的三次多项式都是可以通过线性变换化为这个形式…...