跳到正文
MAKI分享
返回

【记录】Windows Powershell命令调用ffmpeg批量m4a转mp3 & flac

更新于:
MAKI

一、下载和配置ffmpeg所需环境

1.下载ffmpeg

对于Windows,最推荐的来源是 gyan.dev

打开浏览器,访问 https://www.gyan.dev/ffmpeg/builds/

选择并下载文件:

您会看到多个版本。请在 “release builds” 部分找到名为 ffmpeg-release-full.7z 的文件并点击下载。这个“full”版本包含了所有常用的库和功能。

2.解压文件:

下载的是一个 .7z 压缩包,您可能需要安装 7-Zip 或 Bandizip 等免费解压软件来打开它。

将压缩包解压到一个永久、简单的位置。例如,直接解压到 C: 盘根目录,并将其重命名为 ffmpeg。

最终,您的 ffmpeg.exe 文件应该位于类似 C:\ffmpeg\bin\ffmpeg.exe 的路径下。

3.配置环境变量 (最关键的一步):

为了能在任何位置使用 ffmpeg 命令,您需要将它所在的 bin 文件夹路径添加到系统环境变量中。

按下键盘上的 Win 键,直接输入“环境变量”,然后选择“编辑系统环境变量”。

在弹出的“系统属性”窗口中,点击右下角的“环境变量…”按钮。

在下方的“系统变量”区域里,找到并双击名为 Path 的变量。

在弹出的“编辑环境变量”窗口中,点击右上角的“新建”。

将您刚才解压的 bin 文件夹的完整路径(例如 C:\ffmpeg\bin)粘贴进去。

一路点击“确定”保存所有窗口。

4.验证安装:

重新打开一个新的命令提示符(CMD)或 PowerShell 窗口(注意:必须是新的,旧的窗口不会加载新的环境变量)。

输入以下命令并按回车:

ffmpeg -version

如果您看到一大段关于 ffmpeg 版本和库的信息输出,而不是“不是内部或外部命令”,那么恭喜您,安装成功!

二、使用Powershell执行脚本(脚本如下,记得修改用户配置区域)

1.批量m4a转mp3

# ===================================================================

# --- 用户配置区域 ---

# ===================================================================

# 1. 【请修改这里】指定您存放音视频文件的【源文件夹】路径

$sourceFolder = “源文件夹路径”

# 2. 【请修改这里】指定您希望存放 MP3 文件的【输出文件夹】路径

$outputFolder = “目标文件夹路径”

# 3. 【新增可选修改】是否要压缩源文件夹中已存在的 MP3 文件?

#    设置为 $true  -  脚本会处理 .m4a 和 .mp3 文件,将它们统一转换为目标质量的 MP3。

#    设置为 $false -  脚本将只转换 .m4a 文件,忽略所有 .mp3 文件 (原始功能)。

$processExistingMP3s = $true

# 4. 【新增可选修改】设置输出 MP3 的质量参数 (此设置对 M4A 转换和 MP3 压缩同时生效)

#    方案A (推荐, 动态比特率): 使用 -q:a 4 到 -q:a 6 之间的值。数值越大,文件越小,音质越低。

#      “-q:a 5”  (约 130kbps) 是音质和体积的绝佳平衡点。

#    方案B (固定比特率): 使用 “-b:a 128k”, “-b:a 192k” 等。

$ffmpegQualityArgs = “-q:a 5”

# 5. 【可选修改】在这里设置你想同时运行的线程数 (推荐设置为您的 CPU 核心数)

$maxJobs = 4

# ===================================================================

# --- 脚本主体 (以下部分无需修改) ---

# ===================================================================

# 检查源文件夹是否存在

if (-not (Test-Path -Path $sourceFolder -PathType Container)) {

    Write-Host “错误:指定的源文件夹不存在,请检查路径: $sourceFolder” -ForegroundColor Red

    Read-Host “按回车键退出”

    exit

}

# 检查输出文件夹是否存在,如果不存在则创建它

if (-not (Test-Path -Path $outputFolder -PathType Container)) {

    Write-Host “指定的输出文件夹不存在,将自动创建: $outputFolder” -ForegroundColor Yellow

    try {

        New-Item -ItemType Directory -Path $outputFolder -ErrorAction Stop | Out-Null

    } catch {

        Write-Host “错误:无法创建输出文件夹,请检查路径或权限。” -ForegroundColor Red

        Read-Host “按回车键退出”

        exit

    }

}

# 【新增安全检查】如果处理 MP3 且源和输出文件夹相同,则停止以防覆盖

if ($processExistingMP3s -and ($sourceFolder.TrimEnd(’\’) -eq $outputFolder.TrimEnd(’\’))) {

    Write-Host “错误:为了防止意外覆盖原始文件,当 ’`$processExistingMP3s’ 设置为 `$true 时,” -ForegroundColor Red

    Write-Host “【源文件夹】和【输出文件夹】不能是同一个路径。” -ForegroundColor Red

    Read-Host “按回车键退出”

    exit

}

# 根据配置获取要处理的文件列表

$fileTypes = @(“*.m4a”)

$modeMessage = “模式:仅转换 M4A 文件”

if ($processExistingMP3s) {

    $fileTypes += “*.mp3”

    $modeMessage = “模式:转换 M4A 文件并压缩 MP3 文件”

}

Write-Host $modeMessage -ForegroundColor Cyan

$files = Get-ChildItem -Path (Join-Path -Path $sourceFolder -ChildPath ’*’) -File -Include $fileTypes

# 检查是否有文件需要处理

if ($files.Count -eq 0) {

    Write-Host “在指定的源文件夹中没有找到任何需要处理的文件。” -ForegroundColor Yellow

    Read-Host “按回车键退出”

    exit

}

Write-Host “找到 $($files.Count) 个文件,准备开始处理…”

# 循环处理文件

foreach ($file in $files) {

    $outputName = Join-Path -Path $outputFolder -ChildPath ($file.BaseName + “.mp3”)

    if (Test-Path -Path $outputName) {

        Write-Host “跳过,目标文件已存在: $($outputName)” -ForegroundColor Gray

        continue

    }

    while (@(Get-Job -State Running).Count -ge $maxJobs) {

        Start-Sleep -Seconds 1

    }

    Write-Host “开始处理: $($file.Name)” -ForegroundColor Green

    # 【已修正】使用 ArgumentList 和 param 块来稳定地向后台任务传递参数

    Start-Job -ScriptBlock {

        param(

            $p_inputFile,

            $p_outputFile,

            $p_qualityArgs

        )

        # 将质量参数字符串分割成数组,以便正确传递给 ffmpeg.exe

        $ffmpegParams = $p_qualityArgs.Split(’ ’)

        # -y: 覆盖, -i: 输入, -vn: 无视频, -acodec libmp3lame: MP3编码器, -loglevel error: 精简输出

        ffmpeg -y -i “$p_inputFile” -vn -acodec libmp3lame $ffmpegParams “$p_outputFile” -loglevel error

    } -ArgumentList $file.FullName, $outputName, $ffmpegQualityArgs

}

# 等待所有剩余的任务完成

Write-Host “所有任务已启动,正在后台处理,请稍候…”

while (Get-Job) {

    Get-Job | Wait-Job -Any | ForEach-Object {

        # 检查任务是否有错误输出

        if ($.State -eq ‘Failed’ -or $.ChildJobs[0].Error.Count -gt 0) {

            # 从 Job 的 Name 属性中提取原始文件名 (这是一个小技巧,因为 Start-Job 默认用 JobN 命名)

            # 我们在处理循环中没有给Job命名,所以这个方法无效,但保留错误输出依然重要。

            Write-Host “一个任务处理失败:” -ForegroundColor Red

            # 输出详细错误

            $_ | Receive-Job | ForEach-Object {

                if ($_ -is [System.Management.Automation.ErrorRecord]) {

                    Write-Host $_.ToString() -ForegroundColor Red

                }

            }

        }

        # 接收并移除任务

        Receive-Job $_ | Out-Null

        Remove-Job $_

    }

}

Write-Host “全部处理完成!转换/压缩后的 MP3 文件已保存在 ‘$outputFolder’ 文件夹中。” -ForegroundColor Magenta

Read-Host “按回车键退出” #===================================================================

2.批量m4a转flac

# =================================================================== # --- 用户配置区域 --- # ===================================================================

# 1. 【请修改这里】指定您存放m4a文件的【源文件夹】路径 $sourceFolder = “请在这里粘贴您的源文件夹路径”

# 2. 【请修改这里】指定您希望存放FLAC文件的【输出文件夹】路径 $outputFolder = “请在这里粘贴您的输出文件夹路径”

# 3. 【可选修改】在这里设置你想同时运行的线程数 (推荐设置为您的CPU核心数) $maxJobs = 4

# =================================================================== # --- 脚本主体 (以下部分无需修改) --- # ===================================================================

# 检查源文件夹是否存在 if (-not (Test-Path -Path $sourceFolder -PathType Container)) { Write-Host “错误:指定的源文件夹不存在,请检查路径: $sourceFolder” -ForegroundColor Red Read-Host “按回车键退出” exit }

# 检查输出文件夹是否存在,如果不存在则创建它 if (-not (Test-Path -Path $outputFolder -PathType Container)) { Write-Host “指定的输出文件夹不存在,将自动创建: $outputFolder” -ForegroundColor Yellow try { New-Item -ItemType Directory -Path $outputFolder -ErrorAction Stop | Out-Null } catch { Write-Host “错误:无法创建输出文件夹,请检查路径或权限。” -ForegroundColor Red Read-Host “按回车键退出” exit } }

# 获取所有m4a文件 $files = Get-ChildItem -Path $sourceFolder -Filter *.m4a

# 检查是否有m4a文件需要转换 if ($files.Count -eq 0) { Write-Host “在指定的源文件夹中没有找到任何 .m4a 文件。” -ForegroundColor Yellow Read-Host “按回车键退出” exit }

Write-Host “找到 $($files.Count) 个 .m4a 文件,准备开始转换为 FLAC…”

# 循环处理文件 foreach ($file in $files) { # 构造输出文件名 $outputName = Join-Path -Path $outputFolder -ChildPath ($file.BaseName + “.flac”)

# 如果同名的flac文件已经存在,则跳过 if (Test-Path -Path $outputName) { Write-Host “跳过已存在的文件: $($file.Name)” -ForegroundColor Cyan continue }

# 等待直到当前运行的任务数小于最大值 while (@(Get-Job -State Running).Count -ge $maxJobs) { Start-Sleep -Seconds 1 }

# 在后台启动一个新的ffmpeg转换任务 Write-Host “开始转换: $($file.Name) -> $($outputName)” -ForegroundColor Green Start-Job -ScriptBlock { # 接收传递过来的参数 param($inputFile, $outputFile) # 执行ffmpeg命令,-y 参数可以覆盖不完整的旧文件,-vn 移除视频流 # -acodec flac 指定使用flac编码器 # -loglevel error 只显示错误信息,让界面更干净 ffmpeg -y -i “$inputFile” -vn -acodec flac “$outputFile” -loglevel error } -ArgumentList $file.FullName, $outputName }

# 等待所有剩余的任务完成 Write-Host “所有任务已启动,正在后台处理,请稍候…” while (@(Get-Job).Count -gt 0) { # 等待任务完成,然后接收并移除,释放内存 Get-Job | Wait-Job -Any | Receive-Job # 移除已完成或失败的任务 Get-Job | Where-Object { $_.State -ne ‘Running’ } | Remove-Job }

Write-Host “全部转换完成!转换后的FLAC文件已保存在 ‘$outputFolder’ 文件夹中。” -ForegroundColor Magenta Read-Host “按回车键退出”


分享这篇文章:

上一篇
【记录】rsync的基本用法&常用参数详解
下一篇
giffgaff 低成本保号方案,今天你保号了吗--2025.08.07

// 评论