[PConline 资讯]如果你是一名音乐发烧友,那么应该知道Flac这种常见的无损音乐格式。Flac音乐文件支持metadata,用户可以编辑metadata,让音乐文件带有艺术家、所属专辑、音轨等等信息。通常来说,metadata和音频数据并不相关,修改metadata并不会影响音频本身。但是,近日微软官方公布了Win10中存在一个Bug,在Win10中用资源管理器修改Flac文件的metadata,竟会导致音频的损坏! 根据Windows Latest的报道,微软最新发布的一份支持文件披露,如果在Win10的2004或者更高版本中,使用文件资源管理器修改Flac音乐文件的metadata,就会损耗Flac音频文件。这个Bug在Win10专业版、家庭版、企业版、工作站版乃至其他版本的Win10中均有出现。 根据微软本月早些时候发布的支持文件,Win10的文件资源管理器导致了这个错误,它破坏了Flac文件头包含的ID3框架也就是metadata,而这个ID3框架负责存储音频的注释,例如音乐标题、艺术家、专辑、曲目编号等。在Win10上,Flac的处理程序忽视了ID3框架,该程序认为Flac文件在使用4字节的文件头,当Flac文件被Win10编辑的时候,ID3框架被覆盖了,导致没有了开始代码,导致了音乐播放器无法识别被修改后的文件。 因此,在Win10中,如果你直接用文件资源管理器修改Flac音乐文件的标题、艺术家等metadata,会导致该文件无法播放。 幸运的是,微软已经确定了Bug的根本原因,用户可以通过Windows Update升级KB5003214补丁进行修复。 在KB5003214补丁中,微软确认了上文提到的错误已经被修复,修改了Flac的标题、艺术家等metadata后,Flac不会再变得无法播放。而对于已经损坏了的Flac文件,微软则发布了一个PowerShell脚本来进行修复,运行该脚本后Flac文件即可重新播放,不过已经从ID3框架中丢失了的metadata信息并不能恢复。 下面是利用PowerShell脚本修复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、保存文件,在“另存为”对话框中,将目录定位到你想要保存PowerShell脚本的位置; 4、在文件名输入框中,输入“FixFlacFiles.ps1”,将另存为文件的类型更改为Text Documents (*.txt); 5、进入到你保存该PowerShell脚本的目录; 6、右键点击刚刚保存的脚本,然后选择“使用PowerShell运行”; 7、出现提示时,输入无法播放的Flac文件的文件名,然后按下回车键。 微软建议大家安装本月推送的可选累积更新,以避免修改Flac文件metadata出现的问题。 |
正在阅读:Win10竟会损坏用户文件?教你解决这个BugWin10竟会损坏用户文件?教你解决这个Bug
2021-06-03 00:15
出处:PConline原创
责任编辑:censi