play_p3.py 2.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. # 播放p3格式的音频文件
  2. import opuslib
  3. import struct
  4. import numpy as np
  5. import sounddevice as sd
  6. import argparse
  7. def play_p3_file(input_file):
  8. """
  9. 播放p3格式的音频文件
  10. p3格式: [1字节类型, 1字节保留, 2字节长度, Opus数据]
  11. """
  12. # 初始化Opus解码器
  13. sample_rate = 16000 # 采样率固定为16000Hz
  14. channels = 1 # 单声道
  15. decoder = opuslib.Decoder(sample_rate, channels)
  16. # 帧大小 (60ms)
  17. frame_size = int(sample_rate * 60 / 1000)
  18. # 打开音频流
  19. stream = sd.OutputStream(
  20. samplerate=sample_rate,
  21. channels=channels,
  22. dtype='int16'
  23. )
  24. stream.start()
  25. try:
  26. with open(input_file, 'rb') as f:
  27. print(f"正在播放: {input_file}")
  28. while True:
  29. # 读取头部 (4字节)
  30. header = f.read(4)
  31. if not header or len(header) < 4:
  32. break
  33. # 解析头部
  34. packet_type, reserved, data_len = struct.unpack('>BBH', header)
  35. # 读取Opus数据
  36. opus_data = f.read(data_len)
  37. if not opus_data or len(opus_data) < data_len:
  38. break
  39. # 解码Opus数据
  40. pcm_data = decoder.decode(opus_data, frame_size)
  41. # 将字节转换为numpy数组
  42. audio_array = np.frombuffer(pcm_data, dtype=np.int16)
  43. # 播放音频
  44. stream.write(audio_array)
  45. except KeyboardInterrupt:
  46. print("\n播放已停止")
  47. finally:
  48. stream.stop()
  49. stream.close()
  50. print("播放完成")
  51. def main():
  52. parser = argparse.ArgumentParser(description='播放p3格式的音频文件')
  53. parser.add_argument('input_file', help='输入的p3文件路径')
  54. args = parser.parse_args()
  55. play_p3_file(args.input_file)
  56. if __name__ == "__main__":
  57. main()