部分语音类模型需要对入参音频文件做分片处理,下面是一个简单的java分片音频文件的示例,仅支持WAV格式。如需对其他格式音频分片,请参考FFmpeg官方文档。
| 日期 | 版本 | 修订内容 |
|---|---|---|
| 2025-03-05 | v1.6.5.8 | 初始化API文档 |
import javax.sound.sampled.*;
import java.io.File;
import java.io.IOException;
public class AudioSplitter {
// 加载音频文件
public AudioInputStream loadAudioFile(String filePath) throws UnsupportedAudioFileException, IOException {
File audioFile = new File(filePath);
return AudioSystem.getAudioInputStream(audioFile); // 返回音频输入流
}
// 计算切分点
public long[] calculateSplitPoints(AudioInputStream audioStream, long durationInSeconds) {
long totalFrames = audioStream.getFrameLength();
long frameRate = (long) audioStream.getFormat().getFrameRate();
long durationInFrames = totalFrames / frameRate;
long[] splitPoints = new long[(int) (durationInFrames / durationInSeconds)];
for (int i = 0; i < splitPoints.length; i++) {
splitPoints[i] = i * durationInSeconds * frameRate; // 计算每个切分点的帧数
}
return splitPoints; // 返回切分点的数组
}
// 切分音频文件
public void splitAudioFile(AudioInputStream audioStream, long[] splitPoints) throws IOException {
for (int i = 0; i < splitPoints.length; i++) {
long startFrame = splitPoints[i];
long endFrame = (i + 1 < splitPoints.length) ? splitPoints[i + 1] : audioStream.getFrameLength();
AudioInputStream splitStream = new AudioInputStream(audioStream, audioStream.getFormat(), endFrame - startFrame);
// 保存切分后的音频文件
File outputFile = new File("split_audio_" + i + ".wav");
AudioSystem.write(splitStream, AudioFileFormat.Type.WAVE, outputFile);
}
}
public static void main(String[] args) {
AudioSplitter audioSplitter = new AudioSplitter();
try {
// 加载音频文件
AudioInputStream audioStream = audioSplitter.loadAudioFile("path/to/your/audiofile.wav");
// 计算切分点,例如每10秒切分一次
long durationInSeconds = 10;
long[] splitPoints = audioSplitter.calculateSplitPoints(audioStream, durationInSeconds);
// 切分音频文件
audioSplitter.splitAudioFile(audioStream, splitPoints);
System.out.println("音频文件分片完成!");
} catch (UnsupportedAudioFileException | IOException e) {
e.printStackTrace();
}
}
}
import wave
import numpy as np
import os
from typing import List, Tuple
class AudioSplitter:
"""音频切分器"""
def load_audio_file(self, file_path: str) -> Tuple[wave.Wave_read, dict]:
"""
加载音频文件
Args:
file_path: 音频文件路径
Returns:
tuple: (wave对象, 音频信息字典)
"""
try:
audio_file = wave.open(file_path, 'rb')
audio_info = {
'n_channels': audio_file.getnchannels(),
'sampwidth': audio_file.getsampwidth(),
'framerate': audio_file.getframerate(),
'n_frames': audio_file.getnframes(),
'comptype': audio_file.getcomptype(),
'compname': audio_file.getcompname()
}
return audio_file, audio_info
except Exception as e:
raise Exception(f"加载音频文件失败: {e}")
def calculate_split_points(self, total_frames: int, frame_rate: int, duration_in_seconds: int) -> List[int]:
"""
计算切分点
Args:
total_frames: 总帧数
frame_rate: 帧率
duration_in_seconds: 每个片段的秒数
Returns:
list: 切分点列表(帧位置)
"""
try:
total_duration = total_frames / frame_rate
num_segments = int(total_duration // duration_in_seconds)
split_points = []
for i in range(num_segments + 1):
split_point = i * duration_in_seconds * frame_rate
if split_point < total_frames:
split_points.append(split_point)
# 确保最后一个点是文件末尾
if split_points[-1] != total_frames:
split_points.append(total_frames)
return split_points
except Exception as e:
raise Exception(f"计算切分点失败: {e}")
def split_audio_file(self, audio_file: wave.Wave_read, audio_info: dict,
split_points: List[int], output_dir: str) -> List[str]:
"""
切分音频文件
Args:
audio_file: 音频文件对象
audio_info: 音频信息字典
split_points: 切分点列表
output_dir: 输出目录
Returns:
list: 生成的音频文件路径列表
"""
try:
# 创建输出目录
if not os.path.exists(output_dir):
os.makedirs(output_dir)
output_files = []
for i in range(len(split_points) - 1):
start_frame = split_points[i]
end_frame = split_points[i + 1]
frame_count = end_frame - start_frame
# 读取音频数据
audio_file.setpos(start_frame)
audio_data = audio_file.readframes(frame_count)
# 创建输出文件
output_filename = f"split_audio_{i}.wav"
output_path = os.path.join(output_dir, output_filename)
# 写入切分后的音频文件
with wave.open(output_path, 'wb') as output_file:
output_file.setnchannels(audio_info['n_channels'])
output_file.setsampwidth(audio_info['sampwidth'])
output_file.setframerate(audio_info['framerate'])
output_file.writeframes(audio_data)
output_files.append(output_path)
print(f"生成片段 {i}: {output_path} (时长: {(end_frame - start_frame) / audio_info['framerate']:.2f}秒)")
return output_files
except Exception as e:
raise Exception(f"切分音频文件失败: {e}")
finally:
audio_file.close()
def split_audio_simple(file_path: str, segment_duration: int = 10, output_dir: str = "output") -> List[str]:
"""
简单的音频切分函数
Args:
file_path: 音频文件路径
segment_duration: 每个片段的时长(秒)
output_dir: 输出目录
Returns:
list: 生成的音频文件路径列表
"""
try:
splitter = AudioSplitter()
# 加载音频文件
print(f"加载音频文件: {file_path}")
audio_file, audio_info = splitter.load_audio_file(file_path)
print(f"音频信息: {audio_info['n_channels']}声道, "
f"采样率: {audio_info['framerate']}Hz, "
f"总时长: {audio_info['n_frames'] / audio_info['framerate']:.2f}秒")
# 计算切分点
split_points = splitter.calculate_split_points(
audio_info['n_frames'], audio_info['framerate'], segment_duration
)
print(f"将音频切分为 {len(split_points) - 1} 个片段,每个约 {segment_duration} 秒")
# 切分音频文件
output_files = splitter.split_audio_file(audio_file, audio_info, split_points, output_dir)
print(f"音频文件分片完成!共生成 {len(output_files)} 个文件")
return output_files
except Exception as e:
print(f"错误: {e}")
return []
# 使用示例
def main():
"""主函数示例"""
# 示例1: 基本使用
print("=== 基本音频切分 ===")
try:
# 创建一个测试音频文件
audio_file_path = "test_audio.wav"
if not os.path.exists(audio_file_path):
# 创建一个简单的测试音频文件
with wave.open(audio_file_path, 'wb') as f:
f.setnchannels(1)
f.setsampwidth(2)
f.setframerate(44100)
f.writeframes(np.random.randint(-32768, 32767, 44100 * 30).tobytes()) # 30秒音频
result_files = split_audio_simple(
file_path=audio_file_path,
segment_duration=10, # 每10秒切分一次
output_dir="audio_segments"
)
if result_files:
print("切分成功!")
else:
print("切分失败或文件不存在")
except Exception as e:
print(f"基本切分示例失败: {e}")
# 示例2: 错误处理演示
print("
=== 错误处理演示 ===")
try:
# 测试不存在的文件
result = split_audio_simple("nonexistent_file.wav")
if not result:
print("错误处理正常:文件不存在时返回空列表")
except Exception as e:
print(f"错误处理演示: {e}")
if __name__ == "__main__":
main()