站长之家 - 业界 2021-06-02 10:22

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

如果你习惯从在线商城下载 FLAC(自由无损音频压缩编码)格式的音频文件,请不要使用 Windows10系统的资源管理器来编辑元数据。在 Windows10Version2004及更高版本中存在一个错误,如果使用资源管理器修改元数据,就有可能会损坏 FLAC 音频文件。

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

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

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

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

解决方案

1. 打开记事本

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

# Copyright2021Microsoft

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

# Refer to KB5003430for 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 -shr7) -ne0

$ blockType = $ blockType -band0x7F

if ($ blockType -ne0)

{

return $ false

}

$ blockSize = (($ stream.ReadByte() -shl16) -bor ($ stream.ReadByte() -shl8) -bor $ stream.ReadByte())

if ($ blockSize -lt34)

{

return $ false

}

$ minAudioBlockSize = ($ stream.ReadByte() -shl8) -bor $ stream.ReadByte()

$ maxAudioBlockSize = ($ stream.ReadByte() -shl8) -bor $ stream.ReadByte()

if ($ minAudioBlockSize -lt16-or $ maxAudioBlockSize -lt16)

{

return $ false

}

$ minFrameSize = (($ stream.ReadByte() -shl16) -bor ($ stream.ReadByte() -shl8) -bor $ stream.ReadByte())

$ maxFrameSize = (($ stream.ReadByte() -shl16) -bor ($ stream.ReadByte() -shl8) -bor $ stream.ReadByte())

$ sampleInfo = (($ stream.ReadByte() -shl24) -bor ($ stream.ReadByte() -shl16) -bor ($ stream.ReadByte() -shl8) -bor $ stream.ReadByte())

$ sampleRate = $ sampleInfo -shr12

$ channelCount = (($ sampleInfo -shr9) -band0x7) +1

$ bitsPerSample = (($ sampleInfo -shr4) -band0x1F) +1

[UInt64] $ sampleCount = (($ stream.ReadByte() -shl24) -bor ($ stream.ReadByte() -shl16) -bor ($ stream.ReadByte() -shl8) -bor $ stream.ReadByte())

$ sampleCount = (([UInt64] $ sampleInfo -band0xF) -shl32) -bor $ sampleCount

$ MD5HashBytes = New-Object byte[]16

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

$ MD5Hash = [Guid]( $ MD5HashBytes)

if ($ sampleRate -eq0)

{

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 "MD5Audio Sample Hash: $ MD5Hash"

return $ true

}

if ($ choice -eq0)

{

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() -eq0) {}

# 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 well seek back4bytes 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文件的文件名,然后按回车键。

相关话题

推荐关键词

24小时热搜

查看更多内容

大家正在看