Opus简介
Opus是一个有损声音编码的格式,由Xiph.Org基金会开发,之后由互联网工程任务组进行标准化,目标是希望用单一格式包含声音和语音,取代Speex和Vorbis,且适用于网络上低延迟的即时声音传输,标准格式定义于RFC 6716文件。Opus格式是一个开放格式,使用上没有任何专利或限制。
在官方的example测试案例中,就算有30%的丢包率,也能够听清楚人声,这对于即时的声音传输场景来说非常重要。并且它支持动态、无缝的调节比特率与音频带宽,在网络环境多变的场景下更能保证音频的质量。
同时它是WebRTC中默认的音频编码格式、也是WebM视频文件中音频的编码格式。
技术特性
Opus可以处理各种音频应用,包括IP语音、视频会议、游戏内聊天、流音乐、甚至远程现场音乐表演。它可以从低比特率窄带语音扩展到非常高清音质的立体声音乐。支持的功能包括:
- 6 kb/秒到510 kb/秒的比特率;单一频道最高256 kb/秒
- 采样率从8 kHz(窄带)到48 kHz(全频)
- 帧大小从2.5毫秒到60毫秒
- 支持恒定比特率(CBR)、受约束比特率(CVBR)和可变比特率(VBR)
- 支持语音(SILK层)和音乐(CELT层)的单独或混合模式
- 支持单声道和立体声;支持多达255个音轨(多数据流的帧)
- 可动态调节比特率,音频带宽和帧大小
- 良好的鲁棒性丢失率和数据包丢失隐藏(PLC)
- 浮点和定点实现
Opus 标识头
关于Opus的标识头,可以从rfc7845标准文档中找到详细的解答,格式如下:
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 'O' | 'p' | 'u' | 's' |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 'H' | 'e' | 'a' | 'd' |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Version = 1 | Channel Count | Pre-skip |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Input Sample Rate (Hz) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Output Gain (Q7.8 in dB) | Mapping Family| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ :
| |
: Optional Channel Mapping Table... :
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Figure 2: ID Header Packet
Identification header主要由8个参数组成,分别为:
- Magic Signature:固定头,占8个字节,为字符串OpusHead
- Version:版本号,占1字节,固定为0x01
- Channel Count:通道数,占1字节,根据音频流通道自行设置,如0x02
- Pre-skip:回放的时候从解码器中丢弃的samples数量,占2字节,为小端模式,默认设置0x00, 0x00
- Input Sample Rate (Hz):音频流的Sample Rate,占4字节,为小端模式,根据实际情况自行设置
- Output Gain:输出增益,占2字节,为小端模式,没有用到默认设置0x00, 0x00
- Channel Mapping Family:通道映射系列,占1字节,默认设置0x00
- Channel Mapping Table:可选参数,上面的Family默认设置0x00的时候可忽略
Android播放opus
原生播放
从Android 5.0+开始,官方支持opus解码 这意味着 MediaPlayer即可播放opus音频流。
三方播放器播放
ExoPlayer也支持播放opus
本地导入ExoPlayer
Cloning the repository and depending on the modules locally is required when using some ExoPlayer extension modules. It’s also a suitable approach if you want to make local changes to ExoPlayer, or if you want to use a development branch.
First, clone the repository into a local directory and checkout the desired branch:
git clone https://github.com/google/ExoPlayer.git
cd ExoPlayer
git checkout release-v2
Next, add the following to your project’s settings.gradle
file, replacing path/to/exoplayer with the path to your local copy:
gradle.ext.exoplayerRoot = 'path/to/exoplayer'
gradle.ext.exoplayerModulePrefix = 'exoplayer-'
apply from: new File(gradle.ext.exoplayerRoot, 'core_settings.gradle')
You should now see the ExoPlayer modules appear as part of your project. You can depend on them as you would on any other local module, for example:
implementation project(':exoplayer-library-core')
implementation project(':exoplayer-library-dash')
implementation project(':exoplayer-library-ui')
本地打包opus的so库
调用
LibopusAudioRenderer audioRenderer = new LibopusAudioRenderer();
player = new ExoPlayer.Builder(context, audioRenderer).build();
player.addListener(this);
MediaSource mediaSource =
new ProgressiveMediaSource.Factory(
new DefaultDataSourceFactory(context, "ExoPlayerExtOpusTest"),
MatroskaExtractor.FACTORY)
.createMediaSource(uri);
player.prepare(mediaSource);
player.setPlayWhenReady(true);