1. XenForo 1.5.14 中文版——支持中文搜索!现已发布!查看详情
  2. Xenforo 爱好者讨论群:215909318 XenForo专区

科技 Windows 10 BUG会破坏FLAC音频文件 现已修复

本帖由 漂亮的石头2021-06-02 发布。版面名称:新闻聚焦

  1. 漂亮的石头

    漂亮的石头 版主 管理成员

    注册:
    2012-02-10
    帖子:
    488,439
    赞:
    48
    如果你习惯从在线商城下载 FLAC(自由无损音频压缩编码)格式的音频文件,请不要使用 Windows 10 系统的资源管理器来编辑元数据。在 Windows 10 Version 2004 及更高版本中存在一个错误,如果使用资源管理器修改元数据,就有可能会损坏 FLAC 音频文件。

    [​IMG]

    这个 BUG 影响Windows10 专业版、家庭版、企业版、工作站和其他 SKU 版本。根据本月早些时候发布的支持文件,Windows 10的文件资源管理器的错误将破坏某些FLAC文件,这些文件在FLAC头之前包含一个ID3框架。ID3是一个框架,它负责存储信息,如音乐标题、艺术家、专辑、曲目编号等。​

    在 Windows 10 系统,FLAC处理程序忽略了ID3框架,因为它认为FLAC文件在开头使用4字节的fLaC。当音乐文件被用户编辑时,ID3 框架被覆盖了,没有开始代码。因此,音乐播放器无法识别修改后的文件。如果音乐文件的标题、艺术家或其他元数据在文件资源管理器中被改变,音乐文件就不会播放或加载。​

    幸运的是,微软已经确定了根本原因,现在可以通过Windows Update进行修复。在KB5003214更新的更新日志中,微软确认该错误已被修复,如果你改变了他们的标题、艺术家或其他元数据,自由无损音频编解码器(FLAC)音乐文件将不再变得无法播放。​

    对于那些有损坏的音乐文件,微软已经发布了一个新的PowerShell脚本,你可以运行它来使文件再次播放。然而,它不能恢复存储在ID3框架中的丢失的元数据。为了避免FLAC音乐文件在未来出现问题,微软建议应用本月的可选累积更新。​

    解决方案

    1. 打开记事本​

    2. 将以下脚本代码复制到记事本中​


    # Copyright 2021 Microsoft​

    # This script will repair a FLAC file that has been corrupted by Media Foundation in reference to KB5003430.​

    # Refer to KB5003430 for further information​

    param(​

    [parameter(Mandatory =$ true,​

    HelpMessage = "The path to the FLAC file that has been corrupted by Media Foundation",​

    ValueFromRemainingArguments =$ true)]​

    [ValidateScript({ -not [String]::IsNullOrEmpty( $_) -and (Test-Path $_) })]​

    [String] $ File​

    )​

    # We need to back up the current file incase we have any errors​

    $ FileDirectory = Split-Path -Resolve $ File​

    $ Filename = Split-Path -Leaf -Resolve $ File​

    $ FullPath = Join-Path -Resolve $ FileDirectory $ Filename​

    $ Filename = [String]::Format("Backup_{0:yyyyMMdd_hhmmss}_{1}", [DateTime]::Now, $ Filename)​

    $ BackupLocation = Join-Path $ FileDirectory $ Filename​

    Write-Output "Microsoft FLAC Repair Tool. This tool will repair a FLAC audio file that was corrupted when editing its details."​

    Write-Output "Affected File: $ FullPath"​

    Write-Output "A backup of the file will be made: $ BackupLocation"​

    Write-Output "Do you wish to continue?"​

    $ choice =$ host.ui.PromptForChoice("Fixing FLAC Script", "Do you wish to continue", ('&Yes', '&No'), 1)​

    function ParseStreamInfoMetADATABlock([System.IO.FileStream] $ stream)​

    {​

    $ blockType = $ stream.ReadByte()​

    $ lastBlock = ($ blockType -shr 7) -ne 0​

    $ blockType = $ blockType -band 0x7F​

    if ($ blockType -ne 0)​

    {​

    return $ false​

    }​

    $ blockSize = (($ stream.ReadByte() -shl 16) -bor ($ stream.ReadByte() -shl 8) -bor $ stream.ReadByte())​

    if ($ blockSize -lt 34)​

    {​

    return $ false​

    }​

    $ minAudioBlockSize = ($ stream.ReadByte() -shl 8) -bor $ stream.ReadByte()​

    $ maxAudioBlockSize = ($ stream.ReadByte() -shl 8) -bor $ stream.ReadByte()​

    if ($ minAudioBlockSize -lt 16 -or $ maxAudioBlockSize -lt 16)​

    {​

    return $ false​

    }​

    $ minFrameSize = (($ stream.ReadByte() -shl 16) -bor ($ stream.ReadByte() -shl 8) -bor $ stream.ReadByte())​

    $ maxFrameSize = (($ stream.ReadByte() -shl 16) -bor ($ stream.ReadByte() -shl 8) -bor $ stream.ReadByte())​

    $ sampleInfo = (($ stream.ReadByte() -shl 24) -bor ($ stream.ReadByte() -shl 16) -bor ($ stream.ReadByte() -shl 8) -bor $ stream.ReadByte())​

    $ sampleRate = $ sampleInfo -shr 12​

    $ channelCount = (($ sampleInfo -shr 9) -band 0x7) + 1​

    $ bitsPerSample = (($ sampleInfo -shr 4) -band 0x1F) + 1​

    [UInt64] $ sampleCount = (($ stream.ReadByte() -shl 24) -bor ($ stream.ReadByte() -shl 16) -bor ($ stream.ReadByte() -shl 8) -bor $ stream.ReadByte())​

    $ sampleCount = (([UInt64] $ sampleInfo -band 0xF) -shl 32) -bor $ sampleCount​

    $ MD5HashBytes = New-Object byte[] 16​

    $ stream.Read( $ MD5HashBytes, 0, $ MD5HashBytes.Length)​

    $ MD5Hash = [Guid]( $ MD5HashBytes)​

    if ($ sampleRate -eq 0)​

    {​

    return $ false​

    }​

    # Passing these checks means that we likely have a stream info header and can rebuild the file​

    Write-Output "File Stream Information"​

    Write-Output "Sample Rate: $ sampleRate"​

    Write-Output "Audio Channels: $ channelCount"​

    Write-Output "Sample Depth: $ bitsPerSample"​

    Write-Output "MD5 Audio Sample Hash: $ MD5Hash"​

    return $ true​

    }​

    if ($ choice -eq 0)​

    {​

    Copy-Item $ FullPath -Destination $ BackupLocation -Force​

    $ stream = [System.IO.File]::Open( $ FullPath, [System.IO.FileMode]::Open)​

    $ stream.Seek(4, [System.IO.SeekOrigin]::Begin)​

    while ($ stream.ReadByte() -eq 0) {}​

    # We now need to figure out where a valid FLAC metadata frame begins​

    # We are likely pointing to the last byte of the size member so we'll seek back 4 bytes and retry​

    $ flacDataStartPosition = $ stream.Position - 4​

    $ stream.Seek( $ flacDataStartPosition, [System.IO.SeekOrigin]::Begin)​

    while (-not(ParseStreamInfoMetadataBlock( $ stream)))​

    {​

    $ flacDataStartPosition = $ flacDataStartPosition + 1​

    $ stream.Seek( $ flacDataStartPosition, [System.IO.SeekOrigin]::Begin)​

    }​

    # Insert the start code​

    $ stream.Seek( $ flacDataStartPosition, [System.IO.SeekOrigin]::Begin)​

    if (Test-Path "$ FullPath.tmp")​

    {​

    Remove-Item "$ FullPath.tmp"​

    }​

    $ fixedStream = [System.IO.File]::Open(" $ FullPath.tmp", [System.IO.FileMode]::CreateNew)​

    [byte[]] $ startCode = [char[]]('f', 'L', 'a', 'C');​

    $ fixedStream.Write( $ startCode, 0, $ startCode.Length)​

    $ stream.CopyTo( $ fixedStream)​

    $ stream.Close()​

    $ fixedStream.Close()​

    Move-Item -Force "$ FullPath.tmp" $ FullPath​

    }​

    3. 文件菜单上,点击保存。​

    4. 在 "另存为 "对话框中,找到你要保存PowerShell脚本的文件夹。​

    5. 在文件名框中,输入FixFlacFiles.ps1,将保存类型框改为文本文档(*.txt),然后点击保存。​

    6. 在Windows Explorer中,找到你保存的PowerShell脚本。​

    7. 右键单击该脚本,然后单击用PowerShell运行。​

    8. 当有提示时,输入无法播放的FLAC文件的文件名,然后按回车键。​
     
正在加载...