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

import os

import json

import argparse

from pathlib import Path

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

#关键功能就是 audiosegment.from_wav("file.wav") 加载wav文件,audiostart_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 = audiostart_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)

简单代码分析

相关推荐
2601_962295587 分钟前
Python中正则表达式的知识汇总分享
python·正则表达式·模块·语法·匹配
ellenwan202610 分钟前
量化实现的难点,常在规则和流程
人工智能·python
2601_9622986711 分钟前
正则表达式引擎 哪些
java·python·perl·pcre·正则表达式引擎
gf132111133 分钟前
【python_回复邮件】
android·java·python
天空属于哈夫克340 分钟前
企业微信API:企业微信机器人如何开发?
python·机器人·企业微信
Patrick在香港41 分钟前
把 Claude 塞进 pandas 管道:7 条脏地址实测,5 条自动清洗、2 条被闸门拦下
python·pandas·etl·claude·数据清洗
二进制漫游记43 分钟前
PostgreSQL超详细入门教程:Windows安装+Python异步连接+完整增删改查实战
python·postgresql
ynchyong43 分钟前
JavaScript Promise 实战:.then() 与 .catch() 的区别及回调函数封装指南
开发语言·javascript·ecmascript·promise·then
2601_962077601 小时前
从零搭建Python接口自动化测试框架:pytest+requests实战指南
python·pytest·接口自动化·requests·框架搭建
大模型码小白1 小时前
数据可视化:AI处理多维数据的HTML5可视化方案
大数据·前端·javascript·人工智能·机器学习·信息可视化·html5