使用python写的mp4转mp3的转换程序
问Claude:
使用python写一个mp4转mp3的转换程序 实现功能:
1.调用ffmpeg进行转换
2.可以单文件方式也可以批量方式转换,如果程序启动时传入的是单文件的路径,则采用单文件转换方式,如果传入的是目录路径,则将该目录下的文件批量转换
3.如果目录下已存在已转换的MP3文件,则忽略该文件不进行转换
4.可通过传入参数指定转换后的文件的保存路径,默认为保存在视频文件相同目录下
5.MP3的码率可以配置,默认为192K
6.如果程序启动时没有传入任何参数,则提示用户输入参数,并等待用户的输入完成
7.要在控制台里显示转换的进度信息
8.转换完成后播放系统提示音提醒
Claude答:
import os
import sys
import subprocess
import argparse
import platform
import glob
import time
from pathlib import Path
def play_notification_sound():
"""播放系统提示音"""
system = platform.system()
try:
if system == "Windows":
import winsound
winsound.MessageBeep()
elif system == "Darwin": # macOS
subprocess.call(["afplay", "/System/Library/Sounds/Ping.aiff"])
else: # Linux和其他系统
subprocess.call(["paplay", "/usr/share/sounds/freedesktop/stereo/complete.oga"])
except Exception as e:
print(f"无法播放系统提示音: {e}")
def get_duration(file_path):
"""使用ffmpeg获取媒体文件的时长"""
cmd = ["ffmpeg", "-i", file_path, "-f", "null", "-"]
# 使用bytes模式并指定encoding='utf-8', errors='replace'进行解码
result = subprocess.run(cmd, stderr=subprocess.PIPE, stdout=subprocess.PIPE)
# 使用errors='replace'安全地解码,替换无法解码的字符
stderr_text = result.stderr.decode('utf-8', errors='replace')
for line in stderr_text.split('\n'):
if "Duration" in line:
time_str = line.split("Duration: ")[1].split(",")[0].strip()
h, m, s = time_str.split(':')
return float(h) * 3600 + float(m) * 60 + float(s)
return None
def convert_mp4_to_mp3(input_path, output_path=None, bitrate="192k"):
"""使用ffmpeg将MP4文件转换为MP3"""
if output_path is None:
# 使用与输入文件相同的目录,但扩展名为.mp3
output_path = os.path.splitext(input_path)[0] + ".mp3"
# 检查输出文件是否已存在
if os.path.exists(output_path):
print(f"输出文件已存在: {output_path}. 跳过转换。")
return False
# 获取视频时长,用于计算进度
duration = get_duration(input_path)
# 准备ffmpeg命令
cmd = [
"ffmpeg",
"-i", input_path,
"-vn", # 不包含视频
"-acodec", "libmp3lame",
"-ab", bitrate,
"-f", "mp3",
output_path
]
# 启动进程并监控进度 - 不使用universal_newlines,改用bytes模式
process = subprocess.Popen(
cmd,
stderr=subprocess.PIPE,
# 移除universal_newlines=True
)
# 用于进度跟踪的变量
start_time = time.time()
last_update = 0
line_buffer = b""
# 逐行读取输出以更新进度
while True:
chunk = process.stderr.read(1)
if not chunk and process.poll() is not None:
break
if chunk:
line_buffer += chunk
if chunk == b'\n' or chunk == b'\r':
try:
# 安全解码行,替换无法解码的字符
line = line_buffer.decode('utf-8', errors='replace')
if "time=" in line and duration:
# 提取当前时间
time_str = line.split("time=")[1].split()[0]
if ":" in time_str:
h, m, s = time_str.split(':')
current_time = float(h) * 3600 + float(m) * 60 + float(s)
else:
current_time = float(time_str)
# 每秒最多更新一次进度
current = time.time()
if current - last_update >= 1:
progress = min(100, (current_time / duration) * 100)
print(f"\r转换中: {os.path.basename(input_path)} - {progress:.1f}%", end="")
last_update = current
except Exception as e:
# 处理解析错误
pass
line_buffer = b""
# 等待进程完成
process.wait()
print() # 进度完成后换行
# 检查转换是否成功
if process.returncode == 0:
print(f"成功转换: {output_path}")
return True
else:
print(f"转换失败: {input_path}")
return False
def process_input(input_path, output_dir=None, bitrate="192k"):
"""处理单个文件或目录中的所有MP4文件"""
converted_count = 0
total_count = 0
if os.path.isfile(input_path):
# 单文件模式
if not input_path.lower().endswith('.mp4'):
print(f"输入文件不是MP4格式: {input_path}")
return 0, 1
# 确定输出路径
if output_dir:
output_path = os.path.join(output_dir, os.path.splitext(os.path.basename(input_path))[0] + ".mp3")
else:
output_path = os.path.splitext(input_path)[0] + ".mp3"
# 如果输出目录不存在,创建它
os.makedirs(os.path.dirname(output_path), exist_ok=True)
# 执行转换
success = convert_mp4_to_mp3(input_path, output_path, bitrate)
return 1 if success else 0, 1
elif os.path.isdir(input_path):
# 批量模式 - 处理目录中的所有MP4文件
mp4_files = glob.glob(os.path.join(input_path, "*.mp4"))
total_count = len(mp4_files)
if total_count == 0:
print(f"目录中没有找到MP4文件: {input_path}")
return 0, 0
print(f"找到{total_count}个MP4文件等待转换")
for i, file_path in enumerate(mp4_files, 1):
print(f"\n处理文件 {i}/{total_count}: {os.path.basename(file_path)}")
# 确定输出路径
if output_dir:
output_path = os.path.join(output_dir, os.path.splitext(os.path.basename(file_path))[0] + ".mp3")
else:
output_path = os.path.splitext(file_path)[0] + ".mp3"
# 如果输出目录不存在,创建它
os.makedirs(os.path.dirname(output_path), exist_ok=True)
# 执行转换
if convert_mp4_to_mp3(file_path, output_path, bitrate):
converted_count += 1
return converted_count, total_count
else:
print(f"输入路径不存在: {input_path}")
return 0, 0
def main():
parser = argparse.ArgumentParser(description="将MP4视频文件转换为MP3音频文件")
parser.add_argument("input", nargs="?", help="输入MP4文件或包含MP4文件的目录")
parser.add_argument("-o", "--output", help="MP3文件的输出目录(默认:与输入相同)")
parser.add_argument("-b", "--bitrate", default="192k", help="MP3码率(默认:192k)")
args = parser.parse_args()
# 如果没有提供参数,提示用户输入
if not args.input:
print("未提供输入参数。请输入所需信息。")
args.input = input("请输入MP4文件路径或包含MP4文件的目录路径: ").strip()
output_choice = input("是否要指定输出目录? (y/n): ").strip().lower()
if output_choice == 'y':
args.output = input("请输入输出目录路径: ").strip()
bitrate_choice = input("是否要指定自定义码率? (y/n): ").strip().lower()
if bitrate_choice == 'y':
args.bitrate = input("请输入码率 (例如: 128k, 192k, 320k): ").strip()
# 验证输入路径
if not os.path.exists(args.input):
print(f"错误: 输入路径不存在: {args.input}")
return 1
# 如果提供了输出目录,验证它
if args.output and not os.path.isdir(args.output):
try:
os.makedirs(args.output, exist_ok=True)
print(f"已创建输出目录: {args.output}")
except Exception as e:
print(f"创建输出目录时出错: {e}")
return 1
# 处理输入
print(f"\n开始转换过程...")
print(f"输入: {args.input}")
print(f"输出目录: {args.output or '与输入相同'}")
print(f"码率: {args.bitrate}")
print("-" * 50)
start_time = time.time()
converted, total = process_input(args.input, args.output, args.bitrate)
elapsed_time = time.time() - start_time
# 打印摘要
print("\n" + "=" * 50)
print(f"转换完成!")
print(f"成功转换: {converted}/{total} 个文件")
print(f"总耗时: {elapsed_time:.2f} 秒")
print("=" * 50)
# 播放提示音
play_notification_sound()
return 0
if __name__ == "__main__":
sys.exit(main())
这个程序实现了您请求的所有功能:
- 使用ffmpeg进行MP4到MP3的转换
- 支持单文件和批量转换模式:
- 如果输入是文件路径,则只转换该文件
- 如果输入是目录路径,则转换该目录下所有MP4文件
- 如果目标目录已存在对应的MP3文件,则跳过该文件
- 可以通过-o或–output参数指定输出目录
- 可以通过-b或–bitrate参数设置MP3码率,默认为192k
- 如果启动时没有提供参数,会进入交互模式提示用户输入
- 在转换过程中显示进度信息
- 转换完成后播放系统提示音
使用方法
基本用法:
python mp4_to_mp3.py 视频文件.mp4
指定输出目录:
python mp4_to_mp3.py 视频文件.mp4 -o 输出目录
指定码率:
python mp4_to_mp3.py 视频文件.mp4 -b 320k
批量转换整个目录:
python mp4_to_mp3.py 视频目录
无参数启动(会提示输入):
python mp4_to_mp3.py
程序运行需要预先安装ffmpeg,并确保ffmpeg命令可以在系统路径中访问。
❤️ 如果这篇文章对您有帮助,欢迎打赏支持
扫描上方二维码,用微信打赏
