请问如何批量将一个文件夹所有的视频转化为音频文件?

请问如何批量将一个文件夹所有的视频转化为音频文件?

我自己写了一个 AU3 编译的

#include <File.au3>

Global $sourceDir = "C:\Users\user\Downloads\HR - 副本"
Global $outputDir = $sourceDir & "\mp3"
Global $ffmpeg = "D:\ffmpeg-8.0.1-essentials_build\bin\ffmpeg.exe"

If Not FileExists($outputDir) Then DirCreate($outputDir)

Local $files = _FileListToArray($sourceDir, "*.*", 1)
If @error Then Exit

For $i = 1 To $files[0]

    Local $file = $files[$i]
    If Not _IsVideo($file) Then ContinueLoop

    Local $fullPath = $sourceDir & "\" & $file
    Local $name = _GetName($file)
    Local $outPath = $outputDir & "\" & $name & ".mp3"

    ConsoleWrite("处理: " & $file & @CRLF)

    ; ===== 核心:不走 cmd + 压缩音频 =====
    Local $cmd = '"' & $ffmpeg & '" -y -i "' & $fullPath & '" -vn -q:a 5 "' & $outPath & '"'

    Local $ret = RunWait($cmd, "", @SW_HIDE)

    If $ret = 0 And FileExists($outPath) Then
        ConsoleWrite("成功" & @CRLF)
    Else
        ConsoleWrite("失败!!!返回码=" & $ret & @CRLF)
    EndIf

Next

MsgBox(64, "完成", "全部转换完成")


Func _IsVideo($file)
    Local $ext = StringLower(StringRight($file, 4))
    Return ($ext = ".mp4" Or $ext = ".mkv" Or $ext = ".avi" Or $ext = ".mov" Or $ext = ".flv")
EndFunc

Func _GetName($file)
    Local $dot = StringInStr($file, ".", 0, -1)
    Return StringLeft($file, $dot - 1)
EndFunc

格式工厂 里的音频分离器

我看 Media Human Audio Converter 应该可以

(202603231818 吐槽:楼主开了一大串帖子提问,收到很多热心回贴,一点回应都没有。)

微软应用商店里有个 Audio Editor - Music Editor & Converter

自己写的, 基于FFMPEG以及Python.
用来将绝大多数能够遇得到的视频格式无脑的转成AAC, 存入一个新的文件夹, 输出时保留文件名
同时处理十个文件.

#!/usr/bin/env python3
# -*- coding: UTF-8 -*-
import os
import sys
import subprocess
from concurrent.futures import ThreadPoolExecutor, as_completed
from pathlib import Path

# 配置
VIDEO_EXTS = ('.mp4', '.mkv', '.avi', '.mov', '.wmv', '.flv', '.webm', '.ts')
OUTPUT_DIR = "audio_extract"
MAX_WORKERS = 10  # 并行线程数
FFMPEG_CMD = "ffmpeg"

def find_videos():
    """查找当前目录下所有视频文件"""
    videos = []
    for f in os.listdir('.'):
        if f.lower().endswith(VIDEO_EXTS):
            videos.append(f)
    return videos

def should_skip(output_path):
    """
    判断是否应该跳过该文件
    - 文件不存在 → 不跳过(需要转换)
    - 文件存在但大小为0 → 不跳过(覆盖)
    - 文件存在且大小>0 → 跳过
    """
    if not os.path.exists(output_path):
        return False, "新文件"
    
    file_size = os.path.getsize(output_path)
    if file_size == 0:
        # 空文件,删除后重新转换
        os.remove(output_path)
        return False, "空文件(覆盖)"
    
    return True, f"已存在 ({file_size / 1024:.1f} KB)"

def extract_audio(video_path):
    """提取单个视频的音频"""
    filename = Path(video_path).stem
    output_path = os.path.join(OUTPUT_DIR, f"{filename}.m4a")
    
    # 检查是否需要跳过
    skip, reason = should_skip(output_path)
    if skip:
        return ("skip", filename, reason)
    
    cmd = [
        FFMPEG_CMD,
        '-hide_banner',
        '-loglevel', 'quiet',
        '-i', video_path,
        '-vn',
        '-c:a', 'aac',
        '-b:a', '256k',
        '-ar', '44100',
        '-y',
        output_path
    ]
    
    try:
        result = subprocess.run(cmd, capture_output=True, text=True)
        if result.returncode == 0:
            # 验证输出文件确实生成且非空
            if os.path.exists(output_path) and os.path.getsize(output_path) > 0:
                return ("success", filename, None)
            else:
                return ("fail", filename, "输出文件为空")
        else:
            return ("fail", filename, result.stderr[:100])
    except Exception as e:
        return ("fail", filename, str(e))

def main():
    print("=" * 42)
    print("         视频批量转 AAC 256k")
    print("=" * 42)
    print()
    
    # 检查ffmpeg
    try:
        subprocess.run([FFMPEG_CMD, '-version'], capture_output=True, check=True)
    except (subprocess.CalledProcessError, FileNotFoundError):
        print("错误:未找到 FFmpeg,请确保已安装并添加到PATH")
        input("按回车键退出...")
        sys.exit(1)
    
    # 创建输出目录
    os.makedirs(OUTPUT_DIR, exist_ok=True)
    
    # 查找视频
    videos = find_videos()
    total = len(videos)
    
    if total == 0:
        print("未找到视频文件!")
        input("按回车键退出...")
        return
    
    print(f"发现 {total} 个视频文件")
    print(f"输出目录: {OUTPUT_DIR}")
    print(f"并行线程: {MAX_WORKERS}")
    print("-" * 42)
    
    # 多线程并行处理
    stats = {"success": 0, "skip": 0, "fail": 0}
    failed_tasks = []
    
    with ThreadPoolExecutor(max_workers=MAX_WORKERS) as executor:
        future_to_video = {
            executor.submit(extract_audio, v): v for v in videos
        }
        
        for future in as_completed(future_to_video):
            status, filename, info = future.result()
            
            if status == "success":
                print(f"[OK]   {filename}.m4a")
                stats["success"] += 1
            elif status == "skip":
                print(f"[SKIP] {filename}.m4a ({info})")
                stats["skip"] += 1
            else:
                print(f"[FAIL] {filename} - {info}")
                stats["fail"] += 1
                failed_tasks.append((filename, info))
    
    print("-" * 42)
    print(f"结果: 成功 {stats['success']} | 跳过 {stats['skip']} | 失败 {stats['fail']} | 总计 {total}")
    
    if failed_tasks:
        print(f"\n失败详情:")
        for name, err in failed_tasks:
            print(f"  - {name}: {err}")
    
    print()
    input("按回车键退出...")

if __name__ == "__main__":
    main()

AU3脚本没学过,可能是我这边的场景简单,一条命令就能解决。