当前位置: 首页 > news >正文

播放视频时如何调整音频的音量

文章的标题已经表明了,我想提一个简单的问题,播放视频的时候我觉得视频的声音太大或者太小了,我想调整一下声音,怎么办?

我想大多数同学想笑了,这是一个问题吗?每个手机都有调整音量大小的物理按键,你操作一下就行了,例如对Android平台,系统都提供了操作声音音量的设置接口,MediaPlayer提供了setVoume函数,AudioTrack也提供了setVolume函数,你直接设置一下不就行了吗?这个问题似乎有点多余,不太专业。但是我只说一句,让用户频繁的操作,这似乎不是一个友好的应用开发者应该说的话。

那么问题来了,可以在用户无感知的情况下自动调整声音的大小,达到一个让用户满意的音量吗?

又有人开始说了,这个也简单,我还是操作系统提供的了seVolume接口函数,只不过不是让用户操作设置,我自己利用程序操作设置不就行了吗?也能打成神不知鬼不觉的地步。我的意思是,千万别,这样的思路更加糟糕,因为系统提供的setVolume直接操作底层的StreamType对应的输出音量,影响的是手机上所有的应用,你一顿操作猛如虎,直接让手机上的所有应用都被迫接收你这种“比较流氓”的改变。

那么问题来了?能不能在不影响其他外部应用和手机硬件设置的前提下改变输出的音量大小?这是本文需要分享的东西。

在开始之前,我觉得有必要分析一下什么是声音?

声音的本质是一种能量波,由振动而产生的能量波,通过传输介质传输出去。声音有三个属性:

  • 音调:声音频率的高低叫做音调(Pitch),是声音的三个主要的主观属性,即音量(响度)、音调、音色(也称音品) 之一。表示人的听觉分辨一个声音的调子高低的程度。音调主要由声音的频率决定,同时也与声音强度有关

  • 音量:人主观上感觉声音的大小(俗称音量),由“振幅”(amplitude)和人离声源的距离决定,振幅越大响度越大,人和声源的距离越小,响度越大。(单位:分贝dB)

  • 音色:又称声音的品质,波形决定了声音的音色。声音因不同物体材料的特性而具有不同特性,音色本身是一种抽象的东西,但波形是把这个抽象直观的表现。音色不同,波形则不同。典型的音色波形有方波,锯齿波,正弦波,脉冲波等。不同的音色,通过波形,完全可以分辨的。

同等条件下,波长是决定音调高低的因素。

同等条件下,振幅是决定音量高低的因素。

同等条件下,波纹是决定音色因素。

通过上面简单的分析,我们已经知道声音的音量实际上就是由声波的振幅决定的,我们需要调整声波的振幅。播放一个视频,需要经历下面几步:

  • 输入视频url

  • 确定视频的封装格式

  • 开始解封装

  • 识别视频的轨道数据

  • 分离轨道数据,音频轨道、视频轨道

  • 解码视频数据为原始数据,解码音频数据为原始数据

  • 做好音视频同步

  • 渲染视频原始数据,播放音频原始数据

上面加黑标红的部分就是我们改变声音振幅的地方,只有将声音数据解码为原始数据,我们加工原始数据的音频流,然后送到AudioTrack或者OpenSL ES内部播放即可。

例如我们使用开源的ExoPlayer播放器,我们想实现这个功能(当然原生的肯定是没有提供这个功能的)。我们需要在解码出音频数据之后,操作解码之后的音频帧数据,调整振幅,然后将得到的数据输出,渲染播放即可满足要求。下面的代码中volumeFlag表示调整振幅的系数,例如我想将声音的振幅调整为原始的1.2倍,那么volumeFlag就是1.2

  private void scaleSamples(short samples[],
                            int position,
                            int numSamples,
                            float volumeFlag) {
    int fixedPointVolume = (int)(volumeFlag * 4096.0f);
    int start = position * channelCount;
    int stop = start + numSamples * channelCount;


    for(int xSample = start; xSample < stop; xSample++) {
      int value = (samples[xSample] * fixedPointVolume) >> 12;
      if(value > 32767) {
        value = 32767;
      } else if(value < -32767) {
        value = -32767;
      }
      samples[xSample] = (short)value;
    }
  }

但是日常生活中我们衡量声音大小使用dB(分贝)衡量的,如果服务器和客户端联调的话,我肯定是告知当前的平均分贝和标准分贝是多少。

  • 平均分贝:计算音频的每一帧数据的分贝,输出平均分贝

  • 标准分贝:当前情况下多少分贝是最合适的分贝

平均分贝我播放器肯定是无法获知的,视频没有播放完成,我们无法获知,但是服务器知道,可以传到客户端,那么分贝这振幅系数之间如何换算?

result = 20 * log(Cur/Max)
Cur表示当前振幅
Max表示最大振幅
所以声音的分贝总是负的(Android平台下是的)。
volume(dB) = 20 * log(Cur / Max)
(所有Android下面计算的分贝大小总是负的)
  • volume 表示计算出来的分贝值

  • Max表示最大振幅

  • Cur表示当前振幅

输入的参数有两个: MeanVolume , BaseVolume
MeanVolume: 平均分贝
BaseVolume: 基准分贝


BaseVolume - MeanVolume = result
20*log(CurBase/Max) - 20*log(Cur/Max) = result
20*log(CurBase/Cur)=result
CurBase/Cur = 10^(result/20)
CurBase = Cur * 10^(result/20)

所以我们最终决定的调整振幅大小的系统是(10^(result/20))

本文所讲源码均来自项目:https://github.com/JeffMony/PlayerSDK

如果你想看ExoPlayer设置音量大小的详细分析和代码,请移步:
https://www.jianshu.com/p/b5060891ba33,如果你想看Ijkplayer设置音量大小的详细分析和代码,请移步:https://www.jianshu.com/p/1d7d2ea13e0c

相关文章:

  • 视频码控:CBR、VBR和ABR
  • OpenGL ES 相机 LUT 滤镜
  • Android 11 正式发布 | 开发者们的舞台已就绪
  • 刚刚,鸿蒙 OS 2.0 发布!HarmonyOS 将正式开源!
  • 如何给 FFmpeg 添加自定义 Codec 编码器
  • FFmpeg从入门到精通——进阶篇,SEI那些事儿
  • iOS音频采集技术解读:如何实现男女变声的音效?
  • MediaCodec 、x264、faac 实现音视频编码并通过 rtmp 协议实现推流
  • 从《黑神话:悟空》的爆火,浅谈当前游戏从业者面临的机遇与挑战
  • 面试官: 说一下你做过哪些性能优化?
  • NDK系列-如何使用C/C++编写带EGL功能的NativeActivity
  • 短视频 SDK 开发 (一) 开发一款短视频 SDK 需要具备哪些知识?
  • 滴滴AR实景导航背后的技术
  • 国庆假期归来,音视频继续搞起,WebRTC送书活动来啦~~~
  • 「字节跳动直播研发团队」是如何每天护航百万直播间的?
  • 收藏网友的 源程序下载网
  • [译]前端离线指南(上)
  • learning koa2.x
  • PV统计优化设计
  • React中的“虫洞”——Context
  • webpack4 一点通
  • 测试如何在敏捷团队中工作?
  • 从零搭建Koa2 Server
  • 第十八天-企业应用架构模式-基本模式
  • 翻译--Thinking in React
  • 回流、重绘及其优化
  • 基于HAProxy的高性能缓存服务器nuster
  • 开源中国专访:Chameleon原理首发,其它跨多端统一框架都是假的?
  • 模型微调
  • 通信类
  • 微信开源mars源码分析1—上层samples分析
  • 学习Vue.js的五个小例子
  • LIGO、Virgo第三轮探测告捷,同时探测到一对黑洞合并产生的引力波事件 ...
  • MPAndroidChart 教程:Y轴 YAxis
  • 回归生活:清理微信公众号
  • ​Java并发新构件之Exchanger
  • ​LeetCode解法汇总307. 区域和检索 - 数组可修改
  • (1)虚拟机的安装与使用,linux系统安装
  • (10)Linux冯诺依曼结构操作系统的再次理解
  • (14)Hive调优——合并小文件
  • (PHP)设置修改 Apache 文件根目录 (Document Root)(转帖)
  • (二) Windows 下 Sublime Text 3 安装离线插件 Anaconda
  • (一)Spring Cloud 直击微服务作用、架构应用、hystrix降级
  • (转)【Hibernate总结系列】使用举例
  • *p++,*(p++),*++p,(*p)++区别?
  • . Flume面试题
  • .NET Core 将实体类转换为 SQL(ORM 映射)
  • .Net Winform开发笔记(一)
  • .net项目IIS、VS 附加进程调试
  • .w文件怎么转成html文件,使用pandoc进行Word与Markdown文件转化
  • ::
  • @Async注解的坑,小心
  • [ 常用工具篇 ] AntSword 蚁剑安装及使用详解
  • []指针
  • [ffmpeg] aac 音频编码