OPUS常见问题解答(音频编解码器)

2020-08-16 08:13:58

如果您正在查找此常见问题中未涵盖的信息,请尝试Opus主网站或此Wiki的Opus类别中包含的页面。

它主要用于Internet上的交互式语音和音乐传输,但也适用于存储和流媒体应用。它融合了Skype的Silk编解码器和xiph.Org的Celt编解码器的技术。它已由Internet工程任务组(IETF)标准化为RFC 6716。

OPUS自2007年初以来一直在开发中。与XIph.Org、Skype和其他几个组织相关的程序员作为IETF编解码器工作组的一部分,为它的开发和标准化进程做出了贡献。

OPUS与大多数高质量格式(如Vorbis、AAC、MP3)的区别在于具有低延迟(5~66.5ms),而与大多数低延迟格式(如Speex、G.711、GSM)的区别在于支持高音频质量(支持从窄带一直到全频带音频)。

它在广泛的比特率范围内达到或超过现有的编解码器质量,并且其运行延迟比几乎任何现有的压缩格式都要低。

最重要的是,OPUS格式及其参考实现都是在自由的、免版税的许可下提供的。这使得它:

从技术角度看(丢失、延迟、比特率...)。OPUS使Speex过时,也应该替换Vorbis和常见的专有编解码器(例如AAC、MP3等)。

对于Ogg视频文件(使用Theora视频编解码器),您可以使用Opus而不是Vorbis,但是总体大小的减少将是最小的,并且会破坏与现有播放器的兼容性。

对于WebM视频文件,惯例是在使用OPUS作为音频编解码器时使用VP9视频编解码器。

目前,将音频编码为OPUS文件的最佳方式是使用opus-tools包中的opusenc命令行工具。

如果您想要一次编码多个文件(例如您的音乐库),请尝试Opus支持页面中列出的应用程序。

OPUS解码支持现在包含在一些互联网浏览器和许多应用程序中,包括Firefox、foobar2000和VLC,以及GStreamer和FFmpeg等框架。

OPUS是一个相对较新的编解码器(2012年9月标准化),但在不久的将来会有更多的应用程序支持它。

像opusenc这样的OPUS编码工具将很乐意对以96或192 kHz采样的输入文件进行编码。

但是,这些速率的文件在内部转换为48 kHz,然后仅对最高20 kHz的频率进行编码。

原因很简单:有损编解码器的设计目的是在保留可听细节的同时丢弃不相关的信息。由于人耳最多只能听到20千赫(通常低于这一频率)的声音,20千赫以上的频率成分是最先要去除的。

参考Opus源代码是在三个条款的BSD许可下发布的,这是一个非常宽松的开放源码许可。只要满足许可证中规定的一些基本条件,就允许商业使用和分发(包括在专有软件中)。

OPUS还包括在作者认为(希望)与所有开放源码许可证(包括GPL(v2和v3))兼容的条件下,授予这些专利的免版税使用权。

在互联网上,协议和编解码器标准是每个人构建的公共基础设施的一部分。

高质量标准的最大价值在于建立在其之上的系统所提供的创新性和互操作性。当少数各方拥有将标准货币化的垄断权时,该基础设施就不再那么普遍,其他每个人都有更多的理由转而使用自己的解决方案,从而增加了成本,降低了效率。

想象一下,在一个道路系统中,每种类型的汽车都只能在自己制造商的路面上行驶。我们都受益于生活在一个所有道路都相连的世界里。

丝绸编解码器由Skype提交给IETF,作为其在OPUS中集成的一部分,进行了大量修改。这些修改非常重要,不可能只编写翻译器。即使在Opus和旧Silk之间共享代码也会非常复杂。

除了线性预测真丝模式和MDCT CELT模式之外,它还具有混合模式,其中高达8 kHz的语音频率用LP编码,而8到20 kHz之间的语音频率用MDCT编码。这就是OPUS能够在32kbps左右具有如此高的语音质量的原因。

集成的另一个优点是能够在这3种模式之间无缝切换,没有任何声音故障,也没有任何带外信号。

现在Opus已经标准化了,它的发展是停止了,还是可以进一步改进呢?

是的,OPUS可以而且应该改进,因为与大多数ITU-T编解码器不同,OPUS只是根据其解码器来定义的。

只要其产生的比特流能够被参考解码器解码,编码器就可以保持进化。这就是现代MP3编码器(例如LAME)能够改进远远超出最初的L3enc和Dist10参考实现的原因。

虽然Opus编码器不太可能看到如此壮观的发展,但我们肯定希望未来的编码器会比参考编码器更好。

事实上,1.1版本的libopus大大提高了参考编码器的质量。有关更多详细信息,请参阅蒙蒂的演示。

在设计OPUS时,我们首先被要求的一件事就是使费率真正具有适应性,因为我们永远不知道会有什么样的费率可用。这不仅意味着比特率的范围很广,而且能够以很小的增量变化。

这就是OPUS从大约6 kb/s扩展到512 kb/s的原因,增量为0.4 kb/s(一个字节具有20毫秒的帧)。OPU可以具有超过1200个可能的比特率,同时只花费11比特发信号通知比特率,因为UDP已经对分组大小进行了编码。

最后一个方面是OPUS易于通过RTP传输,这可以从OPUS RTP有效载荷格式中看出。例如,甚至可以在没有看到SDP或任何带外信令的情况下解码RTP数据包。

目前,只有几个,但这个名单正在快速增长。请在android.stackexchange.com上参考此问题。您可以随时建议其他应用程序。

也就是说,我们的预发布,甚至git库(Xiph,GitHub)都是相当稳定的,并且经过了适当的测试(无论如何你都应该这样做),可以安全地分发。

只需注意,新特性(从未包含在稳定版本中)的API可能仍会发生变化。

Opus代码库是用C89编写的,应该在绝大多数最近(和不是最近)的CPU上运行。

Opus测试过的一些平台包括x86、x86-64、ARM、Itanium、Blackfin和SPARC。

定点和浮点解码器和编码器实现是同一代码库的一部分。

代码缺省为FLOAT,因此需要使用--enable-fix-point进行配置(如果不使用配置脚本,则定义FIXED_POINT)来构建定点代码。

虽然RFC 6716中的实现定义了该标准,但它可能不是最好和最新的实现。

建立OPUS网站的目的是不断改进实施--在速度、编码质量、设备兼容性等方面--同时仍然符合标准。

OPUS具有可变的帧持续时间,可以动态更改,因此OPUS解码器需要准备好接受持续时间为2.5ms的任意倍数到最大120ms的数据包。

OPUS编码器和解码器不需要具有匹配的采样率或信道计数。建议始终以硬件支持的最高速率(例如48 kHz立体声)进行解码,以便用户获得远端正在发送的任何内容的全部质量。

获得帮助是可能的,但在这样做之前,有几件基本的事情需要尝试:

使用未压缩的音频而不是OPU实现您的应用程序。如果它仍然不起作用,那么问题与作品无关。

如果您仍然不能解决问题,最好的选择是向邮件列表或irc.freenode.net上的#opus IRC频道寻求帮助。

如果您认为您在Opus中发现了错误(而不是在您的应用程序中),请提交错误报告。

请提供我们重现问题的方法。要做到这一点,最好的方法是提供一个输入文件,以及导致错误发生的opusenc/opusdec/opus_demo命令行。

如果命令行工具无法触发该错误,请提供一个简单的补丁或C文件来帮助重现该错误。还请提供任何其他相关信息,如操作系统、CPU、构建选项等。

OPUS自定义是OPUS标准的可选部分,允许8、12、16、24或48 kHz以外的采样率和2.5 ms的倍数以外的帧大小。

OPUS自定义需要OPUS通常不需要的附加带外信令,并禁用许多OPUS编码模式。另外,因为Opus Custom是规范的可选部分,所以使用Opus Custom可能会导致兼容性问题。

如何使用OPU不直接支持的44.1 kHz或其他采样率?

读取或写入OPU的工具应该在必要时在幕后透明地执行采样率转换,从而与其他采样率互操作。特别是,软件开发人员不应使用Opus Custom来支持44.1 kHz,除非在上述非常特殊的情况下。

请注意,它通常是首选的解码器输出为48 kHz,即使你知道原来的输入是44.1 kHz。这不仅是因为您可以跳过重采样,还因为许多较便宜的音频接口在44.1 kHz的输出质量很差。

OPUS-TOOLS软件包源代码包含一个小型、高质量、高性能、BSD许可的重采样器,可用于需要重采样的地方。

但是重采样器不会影响质量吗?直接使用44.1千赫不是更好吗?

不怎么有意思。任何合理的重采样器(SOX、libspeexdsp、libsamplerate等)造成的质量下降。远小于最好的有损编解码器在其最高比特率下造成的失真。如果你不能容忍由一个好的44.1KHz↔重采样器造成的质量下降,那么你从一开始就不应该使用有损的编解码器。类似地,与编解码器的其余部分相比,重采样器中花费的额外CPU很小。不仅如此,许多声卡在播放时只支持48 kHz,因此播放器可以直接播放输出,而不是将其重新采样到48 kHz(例如,对于44.1 kHz的MP3)。因此,OPUS实际上只是将重采样的负担从解码器端转移到编码端。

只支持一个内部速率的一个优点是,它使OPUS能够支持许多功能,包括高效的语音压缩(通过Silk)和实时应用程序。这也意味着所有的质量调优工作都可以花在单个配置上,这有助于带来更好的质量。

可变比特率(VBR)模式允许比特率根据正在编码的音频自动随时间变化,以实现一致的质量。

比特率设置控制所需的质量,其刻度经过校准,以接近将在大量且多样化的音频集合上获得的平均比特率。任何特定音频流的实际比特率可以高于或低于该平均值。

20ms的帧大小适用于大多数应用程序。可以使用较小的帧大小来实现较低的等待时间,但是在给定比特率下具有较低的质量。

大于20ms的大小增加了等待时间,并且通常仅在相当低的比特率下或在用于减少外部开销(例如,通过减少发送的分组数量)时才是有益的。对于文件编码,使用大于20ms的帧大小通常会导致相同比特率的质量变差,因为它限制了编码器可以做出的决定。

OPUS的带内FEC特性通过编码有关先前分组的一些信息来帮助降低分组丢失的危害。

为了利用带内FEC,解码器必须将其输出延迟至少一帧,以便它可以在下一帧上使用DECODE_FEC参数调用解码器,以便重建丢失的帧。如果它与抖动缓冲器集成在一起,效果最好。

小于10ms的帧持续时间和非常高的比特率将使用MDCT模式,其中FEC不可用。

即使在不使用FEC的情况下,将预期的损耗级别告知编码器也会帮助编码器做出更明智的决策。默认情况下,实现假定没有任何损失。

我不能在我的嵌入式平台上使用malloc或许多堆栈。我怎么才能让Opus工作呢?

Libopus的正常构建只在_create()和_delete()调用中使用malloc/free,只要预先创建了编解码器状态,就可以安全地实时使用。

如果libopus是使用-DNONTHREADSAFE_PSEUDOSTACK(而不是VAR_ARRAYS或USE_ALLOCA)构建的,那么它将使用用户提供的堆块而不是堆栈来做很多事情,从而大大降低堆栈使用率。这使得生成的库不是线程安全的,除了有限的嵌入式平台外,不推荐在任何平台上使用。

对于使用Ogg文件的应用程序,有一些Ogg Opus测试向量可用于测试解码器,您可以使用opusdec测试编码器。对于RTP应用程序,opusrtp工具可能很有用。

您的应用程序是否可以处理所有帧大小,包括逐帧更改帧大小?

您的应用程序是否通过使用空包调用解码器来正确响应丢失的包?

这取决于模式、音频带宽、声道数量,甚至取决于可以用复杂性换取质量的复杂性旋钮。它可以在任何最新的PC或智能手机上轻松运行。

对于速度较慢的嵌入式CPU/DSP,所需的CPU数量将根据配置和确切CPU的不同而有所不同,因此您需要进行试验。不要指望Opus在非常慢的设备(如8位微控制器)上运行得很快。

如果您的目标是嵌入式/移动平台,则定点构建可能会更快,因此请确保您在构建系统中使用了--enable-fix-point或定义了FIXING_POINT。

OPUS还有一个复杂性选项,可以用质量换取复杂性。默认值为最高质量和最高复杂性。您可以使用opus_set_Complex()来控制这一点(有关详细信息,请参阅文档)。

如果所有其他方法都失败了,并且您需要优化Opus代码,请参见下一个问题。

这将有助于协调在OPU上所做的努力,并减少将时间浪费在重复工作或走上错误道路的可能性。更多详细信息请参见投稿页面。

这就是说,在我们所知道的免费声学回声消除器(AEC)中,最好的可能是WebRTC代码库中的Google AEC。

阅读BOS(流的开始)页面以枚举所有并发多路复用的流的序列号,识别您想要的OPUS流,并获取其prekip值。

向上读取第一完整音频数据页以计算起始区组位置(因为时间戳可能不是从0开始,例如,如果文件是从在开始之后加入的实况流捕获的)。

在文件末尾附近查找序列号与在标题中找到的序列号相同的页面(假设OPUS数据未与另一个流多路传输,并且文件中没有尾部垃圾,则距离末尾略低于64 kB应足以确保找到页面)。

如果您发现其序列号未包括在原始BOS页面集中的页面,则您有一个链接流。您需要将文件一分为二,以标识第一个链的终点和下一个链的起点,并对链中的每个链接重复此过程。

如果您根本找不到任何页面,或者找到一个页面,其序列号包含在原始的BOS页面集中,但不是您想要的Opus流的序列号,请备份并重试(小心避免重新扫描相同的数据,这可能会产生二次最坏情况下的复杂性)。

如果找到序列号与您想要的OPUS流匹配的页面,请查看其最终区块位置,并计算总持续时间(秒)为(Final_Granule_Position-Initial_Granule_Position-PresKip)/48000.0。

通过直接根据文件内容计算持续时间,可以一次写入文件,而无需任何查找,这对于实况流是必要的。链接还简化了直播流,因为您只需将多个文件通过管道连接到同一网络连接,并进行所有相关的元数据更新等,结果仍然是有效的.opus文件(与用于向MP3流添加元数据的黑客相比)。

打开一个典型的.opus文件(它不是多路复用的,也不是链接的)并计算网络上的持续时间,只需要一个额外的HTTP请求,该请求可以与主请求中的缓冲并行进行。这是默认情况下您将从libopusfile的HTTP后端获得的行为。

在具有许多链接的文件中枚举链边界可能代价很高,但是在我们的测试中,libopusfile使用的数量几乎比(当时)其他一些媒体框架少了一个数量级。将持续时间存储在标题中并不能解决这个问题,因为链中的每个环节都有自己的独立标题。如果链枚举的成本是个问题,避免它的最好方法是将链接存储在单独的文件中(即,不要使用链接)。

按照RFC 7845的建议,将目标调整80毫秒以获得足够的滚动前数据(以确保解码器在到达目标时已收敛)。

使用链接的持续时间和大小(以字节为单位),估计调整目标之前具有完整数据包的最后一个音频数据页的位置。

查找到该位置并向前扫描,直到找到一个包含完整数据包(包含有效区组位置)的音频数据页。

如果您认为您已经足够接近调整后的目标,请向前扫描,直到找到包含完整数据包的下一个音频数据页。

如果调整后的目标位于您找到的具有完整数据包的第一个音频数据页和下一个音频数据页之间,请停止。您可以从这里向前解码,当您到达(原始的、未调整的)目标时开始播放。

否则,返回并使用刚刚找到的页面的区块位置和文件偏移量重新估计查找位置。

Libopusfile包括后备,以防止在其猜测反复出错时出现病态的最坏情况行为。加权二等分可以降级为线性扫描,但是libopusfile最坏的情况是在一个恒定的朴素二等分系数内(即对数)。我们只在手动构建来触发它的文件中观察到过这样的病态行为。

当目标位置在当前位置附近时,libopusfile也会走捷径,以使小搜索更便宜。在最好的情况下,它可以在非常短的文件上永远循环,这些文件的数据包含在单个页面中(例如,使用默认编码器设置不到1秒长),而根本不需要查找。

您可以在此页面上找到有关在包含与其他流(例如,视频)多路复用的OPU的文件中进行搜索的更多信息。

与文件持续时间一样,文件开头的索引与实时流不兼容。这也意味着在文件可以开始在网络上播放之前,必须获取更多的数据,因为即使您不打算查找,也必须读过索引。入内。

.