mirror of
https://github.com/xinnan-tech/xiaozhi-esp32-server.git
synced 2026-07-26 00:53:54 +08:00
Merge branch 'main' into future
This commit is contained in:
@@ -5,8 +5,9 @@ Opus编码工具类
|
||||
|
||||
import logging
|
||||
import traceback
|
||||
|
||||
import numpy as np
|
||||
from typing import Optional, Callable, Any
|
||||
from typing import List, Optional
|
||||
from opuslib_next import Encoder
|
||||
from opuslib_next import constants
|
||||
|
||||
@@ -55,14 +56,13 @@ class OpusEncoderUtils:
|
||||
self.encoder.reset_state()
|
||||
self.buffer = np.array([], dtype=np.int16)
|
||||
|
||||
def encode_pcm_to_opus_stream(self, pcm_data: bytes, end_of_stream: bool, callback: Callable[[Any], Any]):
|
||||
def encode_pcm_to_opus(self, pcm_data: bytes, end_of_stream: bool) -> List[bytes]:
|
||||
"""
|
||||
将PCM数据编码为Opus格式,以流式方式进行处理
|
||||
将PCM数据编码为Opus格式
|
||||
|
||||
Args:
|
||||
pcm_data: PCM字节数据
|
||||
end_of_stream: 是否为流的结束,
|
||||
callback: opus处理方法
|
||||
end_of_stream: 是否为流的结束
|
||||
|
||||
Returns:
|
||||
Opus数据包列表
|
||||
@@ -76,6 +76,7 @@ class OpusEncoderUtils:
|
||||
# 将新数据追加到缓冲区
|
||||
self.buffer = np.append(self.buffer, new_samples)
|
||||
|
||||
opus_packets = []
|
||||
offset = 0
|
||||
|
||||
# 处理所有完整帧
|
||||
@@ -83,7 +84,7 @@ class OpusEncoderUtils:
|
||||
frame = self.buffer[offset : offset + self.total_frame_size]
|
||||
output = self._encode(frame)
|
||||
if output:
|
||||
callback(output)
|
||||
opus_packets.append(output)
|
||||
offset += self.total_frame_size
|
||||
|
||||
# 保留未处理的样本
|
||||
@@ -97,9 +98,11 @@ class OpusEncoderUtils:
|
||||
|
||||
output = self._encode(last_frame)
|
||||
if output:
|
||||
callback(output)
|
||||
opus_packets.append(output)
|
||||
self.buffer = np.array([], dtype=np.int16)
|
||||
|
||||
return opus_packets
|
||||
|
||||
def _encode(self, frame: np.ndarray) -> Optional[bytes]:
|
||||
"""编码一帧音频数据"""
|
||||
try:
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
import io
|
||||
import struct
|
||||
from typing import Callable, Any
|
||||
|
||||
def decode_opus_from_file(input_file):
|
||||
"""
|
||||
从p3文件中解码 Opus 数据,并返回一个 Opus 数据包的列表以及总时长。
|
||||
"""
|
||||
opus_datas = []
|
||||
total_frames = 0
|
||||
sample_rate = 16000 # 文件采样率
|
||||
frame_duration_ms = 60 # 帧时长
|
||||
frame_size = int(sample_rate * frame_duration_ms / 1000)
|
||||
|
||||
def decode_opus_from_file_stream(input_file, callback: Callable[[Any], Any]):
|
||||
"""
|
||||
从p3文件中解码 Opus 数据,由 callback 处理 Opus 数据包。
|
||||
"""
|
||||
with open(input_file, 'rb') as f:
|
||||
while True:
|
||||
# 读取头部(4字节):[1字节类型,1字节保留,2字节长度]
|
||||
@@ -22,13 +25,23 @@ def decode_opus_from_file_stream(input_file, callback: Callable[[Any], Any]):
|
||||
if len(opus_data) != data_len:
|
||||
raise ValueError(f"Data length({len(opus_data)}) mismatch({data_len}) in the file.")
|
||||
|
||||
callback(opus_data)
|
||||
opus_datas.append(opus_data)
|
||||
total_frames += 1
|
||||
|
||||
# 计算总时长
|
||||
total_duration = (total_frames * frame_duration_ms) / 1000.0
|
||||
return opus_datas, total_duration
|
||||
|
||||
def decode_opus_from_bytes_stream(input_bytes, callback: Callable[[Any], Any]):
|
||||
def decode_opus_from_bytes(input_bytes):
|
||||
"""
|
||||
从p3二进制数据中解码 Opus 数据,由 callback 处理 Opus 数据包。
|
||||
从p3二进制数据中解码 Opus 数据,并返回一个 Opus 数据包的列表以及总时长。
|
||||
"""
|
||||
import io
|
||||
opus_datas = []
|
||||
total_frames = 0
|
||||
sample_rate = 16000 # 文件采样率
|
||||
frame_duration_ms = 60 # 帧时长
|
||||
frame_size = int(sample_rate * frame_duration_ms / 1000)
|
||||
|
||||
f = io.BytesIO(input_bytes)
|
||||
while True:
|
||||
@@ -39,4 +52,8 @@ def decode_opus_from_bytes_stream(input_bytes, callback: Callable[[Any], Any]):
|
||||
opus_data = f.read(data_len)
|
||||
if len(opus_data) != data_len:
|
||||
raise ValueError(f"Data length({len(opus_data)}) mismatch({data_len}) in the bytes.")
|
||||
callback(opus_data)
|
||||
opus_datas.append(opus_data)
|
||||
total_frames += 1
|
||||
|
||||
total_duration = (total_frames * frame_duration_ms) / 1000.0
|
||||
return opus_datas, total_duration
|
||||
Reference in New Issue
Block a user