基于 FFmpeg 的 OGG 转 MP3 批量转换方法
🛠️ 1. 环境准备(Windows)
访问 FFmpeg 官网: 🔗 ffmpeg.org/download.html → 点击 Windows → 跳转到 gyan.dev 下载并解压。
💡 参数说明:
ffmpeg/ffprobe: 外部命令行工具,脚本中已指定绝对路径C:\ffmpeg\bin\。-qscale:a 2: 表示高质量 MP3(动态比特率 VBR,范围 0–9,数值越低音质越好)。-y: 自动覆盖同名的目标文件。subprocess.run(): 让 Python 自动调用系统命令行执行转换。
💻 2. Python 转换脚本源码
import os
import subprocess
import json
from pathlib import Path
# 配置 FFmpeg 和 ffprobe 的实际路径
ffmpeg_path = r"C:\ffmpeg\bin\ffmpeg.exe"
ffprobe_path = r"C:\ffmpeg\bin\ffprobe.exe"
download_path = str(Path.home() / "Downloads")
# 用于记录已生成的 MP3 文件名,防止重名冲突
used_names = set()
def get_all_metadata_tags(filepath):
"""使用 ffprobe 提取音频文件所有的元数据标签(Tags)"""
try:
result = subprocess.run([
ffprobe_path, "-v", "quiet",
"-print_format", "json",
"-show_format",
"-show_streams",
filepath
], capture_output=True, text=True, encoding='utf-8', check=True)
if not result.stdout:
print(f"⚠️ ffprobe 没有输出: {filepath}")
return {}
info = json.loads(result.stdout)
tags = {}
# 1. 读取文件格式级别的标签
format_tags = info.get("format", {}).get("tags", {})
for k, v in format_tags.items():
tags[k.upper()] = v
# 2. 读取音频流级别的标签
streams = info.get("streams", [])
for stream in streams:
stream_tags = stream.get("tags", {})
for k, v in stream_tags.items():
tags[k.upper()] = v
return tags
except subprocess.CalledProcessError:
print(f"⚠️ ffprobe 调用失败: {filepath}")
return {}
except json.JSONDecodeError:
print(f"⚠️ JSON 解析失败: {filepath}")
return {}
# 遍历下载文件夹中的所有 .ogg 文件
for root, dirs, files in os.walk(download_path):
for file in files:
if file.lower().endswith(".ogg"):
ogg_path = os.path.join(root, file)
print(f"\n[调试] 正在解析: {ogg_path}")
tags = get_all_metadata_tags(ogg_path)
print(f"元数据内容: {tags}")
# 命名策略:优先使用 标题 - 艺术家
title = tags.get("TITLE")
artist = tags.get("ARTIST")
if title and artist:
name = f"{title} - {artist}"
elif title:
name = title
elif artist:
name = artist
else:
name = os.path.splitext(file)[0] # 无标签则使用原文件名
# 过滤掉 Windows 不支持的特殊字符,只保留字母、数字、空格和部分符号
safe_name = "".join(c for c in name if c.isalnum() or c in " _-").strip()
if not safe_name:
safe_name = "output"
# 防止文件名重复的递增计数器
mp3_filename = safe_name + ".mp3"
counter = 1
while mp3_filename.lower() in used_names or os.path.exists(os.path.join(root, mp3_filename)):
mp3_filename = f"{safe_name}_{counter}.mp3"
counter += 1
used_names.add(mp3_filename.lower())
mp3_path = os.path.join(root, mp3_filename)
# 调用 FFmpeg 执行核心转换逻辑
try:
subprocess.run([
ffmpeg_path, "-y", "-i", ogg_path,
"-codec:a", "libmp3lame", "-qscale:a", "2", mp3_path
], check=True)
print(f"✅ 转换成功:{mp3_path}")
except subprocess.CalledProcessError:
print(f"❌ 转换失败:{ogg_path}")
💡 使用须知
本脚本仅用于个人本地音频文件的格式转换与多媒体库元数据(Metadata)整理,请勿用于任何侵犯第三方版权的非法用途。