You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过PowerShell正确读取MP3文件ID3v2标签中的ISRC信息

PowerShell 提取MP3 ISRC信息落地方案

方案1:原生系统接口读取(推荐,无解析误差)

ID3v2标准中ISRC信息存储在TSRC帧内,不需要做任何字符串匹配,直接调用Windows自带的Shell元数据接口即可读取,和第三方标签工具读取结果一致。

  1. 先遍历属性索引,匹配ISRC对应的属性位(不同Windows版本索引值存在差异):
    $shell = New-Object -ComObject Shell.Application
    # 替换为你的音乐库根目录
    $testFolder = $shell.Namespace('D:\Music')
    0..400 | ForEach-Object {
        $propName = $testFolder.GetDetailsOf($testFolder.Items(), $_)
        if ($propName -match 'ISRC') {
            Write-Host "ISRC属性索引: $_ ,属性名: $propName"
        }
    }
    
  2. 拿到索引后(Win10/11默认索引为292,以实际遍历结果为准),批量遍历所有MP3生成路径-ISRC哈希表:
    $isrcMap = @{}
    $allMp3 = Get-ChildItem -Path 'D:\Music' -Filter *.mp3 -Recurse
    $shell = New-Object -ComObject Shell.Application
    foreach ($mp3 in $allMp3) {
        $currentFolder = $shell.Namespace($mp3.DirectoryName)
        $fileItem = $currentFolder.ParseName($mp3.Name)
        # 将292替换为你上一步查到的索引值
        $isrcValue = $currentFolder.GetDetailsOf($fileItem, 292).Trim()
        if ($isrcValue) {
            $isrcMap[$mp3.FullName] = $isrcValue
        }
    }
    # 输出验证结果
    $isrcMap
    

方案2:二进制解析ID3标签(适配接口读取失败场景)

之前用Get-Content直接读文本提取失败的核心原因:ID3v2文本帧开头的ÿþ是UTF-16LE编码的BOM标记(对应字节0xFF 0xFE),这类编码下每个英文字符占2字节,高字节为0x00,在PowerShell默认文本读取逻辑下会被识别为不可见空字符,占用字符串长度但不显示,直接做字符串偏移截取必然错位。
以下代码严格遵循ID3v2帧结构解析,自动适配编码,不需要手动匹配文本位置:

$isrcMap = @{}
$allMp3 = Get-ChildItem -Path 'D:\Music' -Filter *.mp3 -Recurse
foreach ($mp3 in $allMp3) {
    $fileStream = [System.IO.File]::OpenRead($mp3.FullName)
    $binaryReader = New-Object System.IO.BinaryReader($fileStream)
    # 校验ID3v2头
    $id3Header = [System.Text.Encoding]::ASCII.GetString($binaryReader.ReadBytes(3))
    if ($id3Header -ne 'ID3') {
        $binaryReader.Close()
        $fileStream.Close()
        continue
    }
    # 读取标签总长度
    $binaryReader.ReadBytes(2) | Out-Null
    $binaryReader.ReadByte() | Out-Null
    $sizeBytes = $binaryReader.ReadBytes(4)
    $tagTotalSize = ($sizeBytes[0] -shl 21) -bor ($sizeBytes[1] -shl 14) -bor ($sizeBytes[2] -shl 7) -bor $sizeBytes[3]
    $tagContent = $binaryReader.ReadBytes($tagTotalSize)
    $binaryReader.Close()
    $fileStream.Close()

    # 遍历帧定位TSRC
    $offset = 0
    $targetIsrc = $null
    while ($offset -lt $tagContent.Length - 10) {
        $frameId = [System.Text.Encoding]::ASCII.GetString($tagContent[$offset..($offset+3)])
        $frameSize = [BitConverter]::ToInt32($tagContent[($offset+7)..($offset+4)], 0)
        if ($frameId -eq 'TSRC') {
            $encodingFlag = $tagContent[$offset+10]
            $frameData = $tagContent[($offset+11)..($offset+10+$frameSize-1)]
            $contentEncoding = switch ($encodingFlag) {
                0 { [System.Text.Encoding]::GetEncoding('ISO-8859-1') }
                1 { [System.Text.Encoding]::Unicode }
                3 { [System.Text.Encoding]::UTF8 }
                default { [System.Text.Encoding]::UTF8 }
            }
            $targetIsrc = $contentEncoding.GetString($frameData).Trim([char]0x00, [char]0xFEFF)
            break
        }
        $offset += 10 + $frameSize
    }
    if ($targetIsrc) {
        $isrcMap[$mp3.FullName] = $targetIsrc
    }
}
$isrcMap

注意:不要使用Get-Content读取二进制MP3文件后做固定偏移字符串匹配,一旦标签内存在嵌入封面、自定义字段长度变化,匹配逻辑会完全失效。

内容的提问来源于stack exchange,提问作者AlexRussell

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 07:15:33