批量去除视频音轨的脚本

wen 实用脚本 2

本文目录导读:

批量去除视频音轨的脚本

  1. 方法一:使用 Python + FFmpeg(推荐)
  2. 方法二:纯 Bash/Shell 脚本(Linux/macOS)
  3. 方法三:Windows PowerShell 脚本
  4. 重要提示

使用 Python + FFmpeg(推荐)

安装依赖

# 安装 FFmpeg(如果尚未安装)
# macOS: brew install ffmpeg
# Ubuntu: sudo apt install ffmpeg
# Windows: 从官网下载并添加到 PATH
# 安装 Python 库(可选,用于更高级的功能)
pip install ffmpeg-python

脚本:remove_audio_tracks.py

import os
import subprocess
import argparse
from pathlib import Path
def remove_audio(input_path, output_path=None, keep_original=False):
    """
    去除视频文件的音轨
    Args:
        input_path: 输入视频路径
        output_path: 输出视频路径(默认覆盖原文件)
        keep_original: 是否保留原文件(当覆盖时)
    """
    input_path = Path(input_path)
    if not input_path.exists():
        print(f"错误:文件 {input_path} 不存在")
        return False
    # 确定输出路径
    if output_path:
        output_path = Path(output_path)
    else:
        # 覆盖原文件时,先创建一个临时文件
        output_path = input_path.with_name(f"{input_path.stem}_tmp{input_path.suffix}")
    # FFmpeg 命令:复制视频流,删除所有音频流
    cmd = [
        'ffmpeg',
        '-i', str(input_path),
        '-an',                    # 删除所有音频流
        '-c:v', 'copy',           # 复制视频流(不重新编码)
        '-y',                     # 覆盖输出文件
        str(output_path)
    ]
    try:
        print(f"处理中:{input_path.name}")
        subprocess.run(cmd, check=True, capture_output=True, text=True)
        # 如果是覆盖模式,替换原文件
        if not output_path:
            input_path.unlink()
            output_path.rename(input_path)
        elif output_path != input_path:
            if keep_original:
                print(f"已保存为:{output_path}")
            else:
                input_path.unlink()
                output_path.rename(input_path)
                print(f"已处理:{input_path.name}")
        return True
    except subprocess.CalledProcessError as e:
        print(f"处理失败 {input_path.name}: {e.stderr}")
        # 清理临时文件
        if output_path.exists() and output_path != input_path:
            output_path.unlink()
        return False
def batch_process(input_dir, output_dir=None, recursive=False, keep_original=False):
    """
    批量处理目录中的视频文件
    Args:
        input_dir: 输入目录
        output_dir: 输出目录(None 表示覆盖原文件)
        recursive: 是否递归处理子目录
        keep_original: 是否保留原文件
    """
    input_dir = Path(input_dir)
    if not input_dir.exists():
        print(f"错误:目录 {input_dir} 不存在")
        return
    # 支持的视频格式
    video_extensions = {'.mp4', '.avi', '.mkv', '.mov', '.wmv', '.flv', '.webm', '.m4v'}
    # 收集所有视频文件
    if recursive:
        files = [f for f in input_dir.rglob('*') if f.suffix.lower() in video_extensions]
    else:
        files = [f for f in input_dir.iterdir() if f.suffix.lower() in video_extensions and f.is_file()]
    if not files:
        print("未找到视频文件")
        return
    print(f"找到 {len(files)} 个视频文件")
    # 创建输出目录(如果指定)
    if output_dir:
        output_dir = Path(output_dir)
        output_dir.mkdir(parents=True, exist_ok=True)
    success_count = 0
    fail_count = 0
    for file_path in files:
        if output_dir:
            # 保持相对路径结构(如果递归)
            if recursive:
                rel_path = file_path.relative_to(input_dir)
                out_path = output_dir / rel_path
                out_path.parent.mkdir(parents=True, exist_ok=True)
            else:
                out_path = output_dir / file_path.name
        else:
            out_path = None
        if remove_audio(file_path, out_path, keep_original):
            success_count += 1
        else:
            fail_count += 1
    print(f"\n处理完成:成功 {success_count},失败 {fail_count}")
if __name__ == "__main__":
    parser = argparse.ArgumentParser(description='批量去除视频音轨')
    parser.add_argument('input', help='输入文件或目录')
    parser.add_argument('-o', '--output', help='输出目录(默认覆盖原文件)')
    parser.add_argument('-r', '--recursive', action='store_true', help='递归处理子目录')
    parser.add_argument('-k', '--keep', action='store_true', help='保留原文件(将处理后的文件保存到输出目录)')
    args = parser.parse_args()
    input_path = Path(args.input)
    if input_path.is_file():
        # 处理单个文件
        if args.output:
            output_path = Path(args.output)
            if output_path.is_dir():
                output_path = output_path / input_path.name
            remove_audio(input_path, output_path, args.keep)
        else:
            remove_audio(input_path, keep_original=args.keep)
    elif input_path.is_dir():
        batch_process(args.input, args.output, args.recursive, args.keep)
    else:
        print(f"错误:{args.input} 不是有效的文件或目录")

使用示例

# 1. 处理单个文件,覆盖原文件
python remove_audio_tracks.py video.mp4
# 2. 处理单个文件,保存为新文件
python remove_audio_tracks.py video.mp4 -o video_no_audio.mp4
# 3. 批量处理当前目录所有视频,覆盖原文件
python remove_audio_tracks.py ./
# 4. 批量处理,输出到新目录,保留原文件
python remove_audio_tracks.py ./videos -o ./videos_no_audio -k
# 5. 递归处理所有子目录
python remove_audio_tracks.py ./videos -r -o ./videos_no_audio -k

纯 Bash/Shell 脚本(Linux/macOS)

#!/bin/bash
# 批量去除音轨脚本
# 用法: ./remove_audio.sh [input_dir] [output_dir]
INPUT_DIR="${1:-.}"
OUTPUT_DIR="${2:-./no_audio}"
# 支持的视频格式
EXTENSIONS=("mp4" "avi" "mkv" "mov" "wmv" "flv" "webm" "m4v")
# 创建输出目录
mkdir -p "$OUTPUT_DIR"
# 计数器
total=0
success=0
fail=0
echo "开始处理视频文件..."
# 遍历所有视频文件
for ext in "${EXTENSIONS[@]}"; do
    find "$INPUT_DIR" -type f -iname "*.$ext" -print0 | while IFS= read -r -d '' file; do
        total=$((total + 1))
        # 获取相对路径
        rel_path="${file#$INPUT_DIR/}"
        output_file="$OUTPUT_DIR/$rel_path"
        # 创建输出子目录
        mkdir -p "$(dirname "$output_file")"
        echo "处理中: $rel_path"
        # 使用 FFmpeg 去除音轨
        ffmpeg -i "$file" -an -c:v copy -y "$output_file" 2>/dev/null
        if [ $? -eq 0 ]; then
            echo "  ✓ 成功: $output_file"
            success=$((success + 1))
        else
            echo "  ✗ 失败: $file"
            fail=$((fail + 1))
        fi
    done
done
echo "处理完成!成功: $success, 失败: $fail"

使用 Bash 脚本

# 给脚本添加执行权限
chmod +x remove_audio.sh
# 处理当前目录所有视频
./remove_audio.sh
# 处理指定目录
./remove_audio.sh /path/to/videos
# 指定输入和输出目录
./remove_audio.sh /path/to/videos /path/to/output

Windows PowerShell 脚本

# remove_audio.ps1
param(
    [string]$InputPath = ".",
    [string]$OutputPath = "./no_audio",
    [switch]$Recurse = $false
)
# 支持的视频格式
$extensions = @("*.mp4", "*.avi", "*.mkv", "*.mov", "*.wmv", "*.flv", "*.webm", "*.m4v")
# 创建输出目录
New-Item -ItemType Directory -Force -Path $OutputPath | Out-Null
# 计数器
$total = 0
$success = 0
$fail = 0
Write-Host "开始处理视频文件..." -ForegroundColor Green
# 遍历文件
$files = @()
foreach ($ext in $extensions) {
    if ($Recurse) {
        $files += Get-ChildItem -Path $InputPath -Filter $ext -Recurse -File
    } else {
        $files += Get-ChildItem -Path $InputPath -Filter $ext -File
    }
}
foreach ($file in $files) {
    $total++
    # 计算相对路径
    $relPath = $file.FullName.Substring((Resolve-Path $InputPath).Path.Length + 1)
    $outputFile = Join-Path $OutputPath $relPath
    # 创建输出子目录
    $outputDir = Split-Path $outputFile -Parent
    New-Item -ItemType Directory -Force -Path $outputDir | Out-Null
    Write-Host "处理中: $relPath"
    # FFmpeg 命令
    $ffmpegCmd = "ffmpeg -i `"$($file.FullName)`" -an -c:v copy -y `"$outputFile`""
    try {
        Invoke-Expression $ffmpegCmd 2>$null
        if ($LASTEXITCODE -eq 0) {
            Write-Host "  ✓ 成功" -ForegroundColor Green
            $success++
        } else {
            Write-Host "  ✗ 失败" -ForegroundColor Red
            $fail++
        }
    } catch {
        Write-Host "  ✗ 错误: $_" -ForegroundColor Red
        $fail++
    }
}
Write-Host "`n处理完成!成功: $success, 失败: $fail" -ForegroundColor Green

使用 PowerShell 脚本

# 允许执行脚本(如果需要)
Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass
# 处理当前目录
.\remove_audio.ps1
# 递归处理子目录
.\remove_audio.ps1 -InputPath "C:\videos" -OutputPath "C:\videos_no_audio" -Recurse

重要提示

  1. FFmpeg 必须安装:所有脚本都依赖 FFmpeg,请确保已安装并配置好环境变量。

  2. 速度优势:使用 -c:v copy 参数,不会重新编码视频,只移除音轨,处理速度非常快。

  3. 风险警告:覆盖原文件操作不可逆,建议先备份重要文件。

  4. 输出目录:创建输出目录可以保留原始文件,更安全。

选择适合你操作系统和使用习惯的脚本即可!

抱歉,评论功能暂时关闭!