如何在Windows中使用opuslib库
前言
Hi,everyone,本周笔者在Windows环境下使用python开发上位机时,意外发现需要解码opus音频数据,因此笔者需要在上位机中加入opus的编解码器,在opus官网下载的解码器需要在Linux环境下运行,编译出来是一个ELF文件,而笔者的上位机是基于python开发的,且目标用户都使用Windows环境,因此笔者理所当然地就要解决如何在Windows环境下使用python开发opus编解码器这个问题,笔者使用opuslib + opus.dll的形式解决问题,笔者会提供笔者使用的opus.dll下载链接和配置方式。
你是否需要opuslib
opuslib是一个为libopus音频编码库提供Python绑定的工具包,能够让使用者在Python项目中使用Opus音频编解码器。其核心价值就在于,它将Opus编解码器的强大功能以易于使用的Python接口形式提供出来。很重要的一点是:在opuslib中,无论是将PCM音频流数据编码成Opus数据,还是将Opus数据解码成PCM音频流进行播放,其Opus数据包是裸的,即纯粹的Opus数据,为何要强调这一点?因为有些opus编解码,例如ffmpeg是会在Opus数据外套一层ogg格式,而如果读者正是想要该封装格式的可以使用ffmpeg来编码或解码数据。
所以:
- 你需要使用python来程序来编解码opus音频数据
- 你需要在Windows环境下使用
- 你想要解码或编码纯粹的opus数据,而不是被ogg(或其它)封装后的数据
那么这篇文章可以帮到你,文章不长,可以读读。
下载opuslib
在你的python虚拟环境下使用命令下载opuslib库:
pip install opuslib
此命令会在你当前使用的python虚拟环境下安装opuslib库,但请注意,此时如果你尝试使用导入该库并使用,会报错。
opuslib使用异常
例如:
import opuslib # 导入opuslib库decoder = opuslib.Decoder(48000, 960) # 初始化解码器

从报错信息中可以看到,当你初始化一个opus解码器对象时,会抛出异常,异常信息显示Could not find Opus library. Make sure it is installed.,索引到最后报错的文件可以看到:

可以看到,当没有在lib_location这个变量没有找到库时,就会抛出该异常,提示你它并没有找到相应的opus库。你可以将opuslib理解为一个封装,它本质上没有opus编解码器,而是调用写好的opus编解码器,转换成python形式的接口,方便你在python中调用,因此我们需要手动添加一个可以在Windows环境下运行的opus库进去。
顺便提一嘴:这个
__init__.py文件是在虚拟环境\Lib\site-packages\opuslib\api\__init__.py,虚拟环境是你的虚拟环境名称,笔者这里叫做venv,因此笔者这里的完整路径是:D:\HugoBlog\dev\content\post\useOpuslibInWindows\testopuslib\.venv\lib\site-packages\opuslib\api\__init__.py要提这一嘴是因为在python中__init__.py文件特别多,与api同级下还有个__init__.py,别弄混了。
下载opus.dll
笔者找到了一个可以在Windows下运行的opus动态库(opus.dll),将其放在CSDN资源和百度网盘中,附上链接,大家可以随意下载使用。
【免费】Windows下使用的opus编解码动态库资源-CSDN下载
百度网盘分享-opus.dll提取码: 7aed
配置opus动态库
还记得上面笔者提到的__init__.py文件中的lib_location变量吗,该变量实质上是一个地址,你当然可以使用绝对地址的形式将opus.dll的位置直接写入lib_location,如下所示:


但考虑代码健壮性,也可以这么写:
lib_location = find_library('opus')
current_dir = os.path.dirname(os.path.abspath(__file__)) # 获取当前文件所在目录
lib_location = os.path.join(current_dir, 'opus.dll') # 构建 opus.dll 的完整路径(在同一目录下)
if lib_location is None:raise Exception('Could not find Opus library. Make sure it is installed.')
这段代码的作用是:
- current_dir:获取当前文件的目录,即:
__init__.py的目录 - lib_location:将
current_dir与opus.dll拼接在一起
使用这段代码,读者仅需将opus.dll放在与__init__.py同一目录下即可,如上图所示。
小结
读到这里,读者们应该可以自行使用opuslib来编写opus音频编解码库了,我们来做个小结:
- 使用pip包管理器下载opuslib,但opuslib无法在Windows中直接使用
- 下载opus.dll动态库
- 将opus.dll的地址赋值给opuslib库中的初始化函数,笔者提供相对地址与绝对地址两种方式
那么接下来,笔者再提供一些笔者在编写语音编解码器时踩过的一些坑
pyinstaller无法打包第三方库
笔者目的是使用pyqt做一个上位机,可视化地展示语音解码的波形与播放。关于如何使用pyqt做一个语音播放器,可以看笔者下面这几篇文章
PyAudio库基本知识详解
基于PyQt开发的脚本集合包(十三)
基于PyQt开发的脚本集合包(十四)
在使用pyqt做完了语音播放器后,使用pyinstaller工具,将程序打包成.exe可执行文件,在运行时报错:

这个报错显示exe文件在运行时没有找到一个名为opuslib的库,由于我是用pyinstaller的时候并没有将所有东西压缩成一个单独的exe文件,pyinstaller会将我导入的一些第三方库比如PyQt5、numpy、matplotlib等放在一个名为_internal的目录下,检查该目录发现,并没有opuslib,这个_internal目录与你在编程时的虚拟环境目录很像,存放了你使用pip下载的第三方库。
因此,这里可能是pyinstaller出于某种原因,并没有将虚拟环境目录下的opuslib一起打包进来,笔者在网上找了许多方法,都比较复杂,笔者在这里提供一个简单的,直接将你使用的opuslib库拖到_internal目录下即可。
这样就能解决No module named 'opuslib'的问题。
Opus解码器样例
这里笔者给出一个opus的解码器样例:
import opuslibclass OpusDecoder:def __init__(self):# 配置参数SAMPLE_RATE = 48000 # Opus 标准采样率(支持 8000, 12000, 16000, 24000, 48000)CHANNELS = 1 # 声道数(1=单声道,2=立体声)FRAME_SIZE_MS = 20 # 每帧时长(毫秒,Opus 常用 20ms 的帧)# 计算每帧的样本数(如 48000Hz * 20ms = 960 样本/帧)self.FRAME_SIZE = int(SAMPLE_RATE * FRAME_SIZE_MS / 1000)# 初始化 Opus 解码器self.decoder = opuslib.Decoder(SAMPLE_RATE, CHANNELS)passdef decode_opus_to_pcm(self,opusfile,pcmfile):self.INPUT_OPUS_FILE = opusfileself.OUTPUT_PCM_FILE = pcmfile# 打开文件并解码with open(self.INPUT_OPUS_FILE, "rb") as opus_file, open(self.OUTPUT_PCM_FILE, "wb") as pcm_file:while True:# 读取 Opus 帧(注意:这里假设文件是裸 Opus 流,无 Ogg 封装)opus_frame = opus_file.read(40) # 40 是经验值,需根据实际帧大小调整# 无更多数据时退出循环if not opus_frame:break# 解码为 PCMpcm_data = self.decoder.decode(opus_frame, self.FRAME_SIZE)# 写入 PCM 文件pcm_file.write(pcm_data)# print("解码完成!输出文件:", self.OUTPUT_PCM_FILE)# return self.OUTPUT_PCM_FILE
# 测试样例
OpusDecoder().decode_opus_to_pcm("input.opus","output.pcm")
输入input.opus的opus数据(裸的opus数据,二进制文件),即可解码得到output.pcm音频流数据(裸的pcm数据,二进制文件,可直接在adobe之类的软件播放)
好啦,如果本文有一点点帮助你,那荣幸之至,后续笔者也会考虑出一文解释一下opus的数据,其实从opus的数据包中可以逆推出一些信息,如果想看的话点赞留言催更,笔者会尽快出文,祝你变得更强!
