代码分析 长音频分割为短音频

import os

import json

import argparse

from pathlib import Path

#简单易用的音频处理库 pydub 支持加载、切片、格式转换、音量调整,底层依赖ffmpeg

#关键功能就是 audiosegment.from_wav("file.wav") 加载wav文件,audio[start_ms:end_ms]按毫秒切片 clip.export("out.wav",format="wav")导出音频

from pydub import AudioSegment

#这个函数,里面的三个参数是jsonl路径,音频路径,输出路径

def split_audio_by_jsonl(jsonl_path, audio_dir, output_dir):

audio_dir = Path(audio_dir)#为啥要这样?将传入的字符转换为一个pathlib.path对象,因为path可以拼接路径audio_dir / "file.wav",而不是 os.path.join(audio_dir, "file.wav")

#还可以直接调用方法.exists() .is_file()等

output_dir = Path(output_dir)#指向命令行参数,意义同上

#parents=true 如果目录路径中包含多级不存在的父目录,自动递归创建所有上级目录

output_dir.mkdir(parents=True, exist_ok=True)#如果没有便创建

#打开jsonl文件,逐行读取

with open(jsonl_path, 'r', encoding='utf-8') as f:

for line_num, line in enumerate(f, 1):

line = line.strip()

if not line:

continue

#json.loads(line)将字符串line 解析为Python字典item

#.get("key") 获取字段key

try:

item = json.loads(line)

key = item.get("key")

#.get("utterances",[])获得utterances字段,若缺失则默认为空列表

utterances = item.get("utterances", [])

if not key or not utterances:

print(f"⚠️ 跳过第 {line_num} 行:缺少 key 或 utterances")

continue

#看一下这段代码,首先是直接audio_dir/key作为路径,没有的话 加上wav后缀,要是还没有就是没有

查找原始音频文件(支持 .wav)

audio_path = audio_dir / key

if not audio_path.exists():

尝试带 .wav 后缀(如果 key 本身不含���

audio_path = audio_dir / (key + ".wav")

if not audio_path.exists():

print(f"❌ 第 {line_num} 行:未找到音频文件 {key}(或 {key}.wav)")

continue

print(f"🔊 正在处理: {key}")

#然后这个是找到了,用pydub库加载一个.wav格式的音频文件,将其转化为一个可编程操作的音频对象

  • pydub 会调用底层音频引擎(通常是 ffmpeg)读取文件;
  • 将音频数据加载到内存中,转换为 AudioSegment 对象;
  • 对象内部包含:
    • 音频采样率(如 16000 Hz)
    • 通道数(单声道/立体声)
    • 采样位深(如 16-bit)
    • 原始音频数据(以 bytesarray 存储)

audio = AudioSegment.from_wav(audio_path)

#对于utternaces 这里面很多条的 得到开始和结束的 得到text部分,我这个jsonl文件懒得粘贴条目,应该就是里面有 开始 结束 和text这三部分

for utt in utterances:

start_ms = utt.get("start_time")

end_ms = utt.get("end_time")

text = utt.get("text", "").strip()

if start_ms is None or end_ms is None:

continue

确保时间不越界

start_ms = max(0, start_ms)

end_ms = min(len(audio), end_ms)

#很健壮

if end_ms <= start_ms:

continue

切片

clip = audio[start_ms:end_ms]

生成文件名:key_start_end.wav

safe_key = key.replace(".wav", "") # 避免重复 .wav

#这是对于文件的命名,就是以文件名命名,但是不要.wav 然后加上开始和结束时间 作为命名

filename = f"{safe_key}{start_ms}{end_ms}.wav"

#构建路径

output_path = output_dir / filename

clip.export(output_path, format="wav")

print(f" ✅ 保存: {filename}")

except Exception as e:

print(f"❌ 第 {line_num} 行处理出错: {e}")

print(f"\n✅ 所有音频切分完成!输出目录: {output_dir}")

def main():

#命令行参数

parser = argparse.ArgumentParser(

description="根据 JSONL 中的 utterances 时间戳切分音频"

)

parser.add_argument("jsonl_file", help="输入的 .jsonl 文件路径")

parser.add_argument("audio_dir", help="原始音频所在文件夹")

parser.add_argument("output_dir", help="切分后音频的输出文件夹")

args = parser.parse_args()

split_audio_by_jsonl(args.jsonl_file, args.audio_dir, args.output_dir)

简单代码分析

相关推荐
Black蜡笔小新1 小时前
视频融合平台EasyCVR远程监控技术在沙尘暴交通监控中的应用
音视频
xiaoxue..1 小时前
栈的全面解析:ADT、实现与应用
javascript·数据结构·面试
DevUI团队1 小时前
Angular开发者必看:深度解析单元测试核心技巧与最佳实践
前端·javascript·angular.js
Wpa.wk1 小时前
自动化测试环境配置-java+python
java·开发语言·python·测试工具·自动化
带刺的坐椅2 小时前
AI 应用工作流:LangGraph 和 Solon AI Flow,我该选谁?
java·python·ai·solon·flow·langgraph
工业互联网专业2 小时前
图片推荐系统_django+spider
python·django·毕业设计·源码·课程设计·spider·图片推荐系统
q***64972 小时前
SpringMVC 请求参数接收
前端·javascript·算法
Lwcah2 小时前
Python | LGBM+SHAP可解释性分析回归预测及可视化算法
python·算法·回归
@一辈子爱你2 小时前
归来九十余日:在时代的夹缝中,与你共筑一道光
python