Tóm tắt
Bản cập nhật này đề cập đến sự cố mã hóa siêu dữ liệu khiến tệp nhạc Free Lossless Audio Codec (FLAC) trở nên không thể phát nếu tiêu đề, nghệ sĩ hoặc siêu dữ liệu khác của chúng bị thay đổi.
Nguyên nhân
Sự cố này có thể xảy ra khi tệp FLAC có chứa khung ID3 trước tiêu đề FLAC. Khung ID3 chứa siêu dữ liệu như chức danh và nghệ sĩ. Bộ xử lý thuộc tính FLAC giả định rằng tất cả các tệp FLAC bắt đầu với mã bắt đầu 4 byte fLaC và không tính đến khung ID3 ở đầu tệp. Do đó, khung ID3 sẽ bị ghi đè mà không có mã bắt đầu fLaC kết xuất tệp không thể phát được.
Giải pháp
Để ngăn sự cố này đối với các tệp nhạc FLAC trong tương lai, hãy cài đặt Bản xem trước 25/05/2021—KB5003214 (Bản dựng HĐH 19041.1013, 19042.1013 và 19043.1013).
Để sửa chữa các tệp nhạc FLAC bị ảnh hưởng, hãy chạy tập lệnh PowerShell sau.
Quan trọng: Tập lệnh này sẽ không khôi phục siêu dữ liệu bị mất được lưu trữ trong khung ID3. Tuy nhiên, tính năng này sẽ làm cho tệp có thể phát lại.
-
Mở Notepad.
-
Sao chép và dán tập lệnh sau đây vào notepad:
# Copyright 2021 Microsoft
# Tập lệnh này sẽ sửa chữa tệp FLAC mà Media Foundation đã hỏng tham chiếu đến KB5003430.
# Tham khảo KB5003430 để biết thêm thông tin
param(
[parameter(Mandatory=$true,
HelpMessage="Đường dẫn đến tệp FLAC đã bị hỏng bởi Media Foundation",
ValueFromRemainingArguments=$true)]
[ValidateScript({ -not [String]:IsNullOrEmpty($_) -and (Test-Path $_) })]
[String]$File
)
# Chúng tôi cần sao lưu dự phòng lỗi của tệp hiện tại
$FileDirectory = hiệu Split-Path -Giải quyết $File
$Filename = cây Split-Path -Lá -Giải quyết vấn $File
$FullPath = tìm Join-Path -Giải quyết $FileDirectory $Filename
$Filename = [String]:Format("Backup_{0:yyyyMMdd_hhmmss}_{1}", [DateTime]::Now, $Filename)
$BackupLocation = Join-Path $FileDirectory $Filename
Write-Output "Công cụ Sửa chữa Microsoft FLAC. Công cụ này sẽ sửa chữa tệp âm thanh FLAC bị hỏng khi chỉnh sửa các chi tiết của tệp đó."
Write-Output "Tệp bị ảnh hưởng: $FullPath"
Write-Output "Một bản sao lưu tệp sẽ được thực hiện: $BackupLocation"
Write-Output "Bạn có muốn tiếp tục không?"
$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)
{
trả lại $false
}
$blockSize = (($stream. ReadByte() -shl 16) -bor ($stream. ReadByte() -shl 8) -bor $stream. ReadByte())
if ($blockSize -lt 34)
{
trả lại $false
}
$minAudioBlockSize = ($stream. ReadByte() -shl 8) -bor $stream. ReadByte()
$maxAudioBlockSize = ($stream. ReadByte() -shl 8) -bor $stream. ReadByte()
if ($minAudioBlockSize -lt 16 -hoặc $maxAudioBlockSize -lt 16)
{
trả lại $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
$MD 5HashBytes = New-Object byte[] 16
$stream. Read($MD 5HashBytes, 0, $MD 5HashBytes.Length)
$MD 5Hash = [Guid]($MD 5HashBytes)
if ($sampleRate -eq 0)
{
trả lại $false
}
# Chuyển qua những kiểm tra này nghĩa là chúng tôi có thể có tiêu đề thông tin dòng và có thể dựng lại tệp
Write-Output "Thông tin Dòng Tệp"
Write-Output "Sample Rate: $sampleRate"
Write-Output "Audio Channels: $channelCount"
Write-Output "Độ sâu Mẫu: Độ $bitsPerSample"
Write-Output "Băm Mẫu Âm thanh MD5: $MD 5Hash"
trả lại $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)
trong khi ($stream. ReadByte() -eq 0) {}
# Bây giờ chúng ta cần tìm xem khung siêu dữ liệu FLAC hợp lệ bắt đầu từ đâu
# Chúng tôi có thể đang trỏ tới byte cuối cùng của thành viên kích cỡ nên chúng tôi sẽ tìm lại 4 byte và lần nữa
$flacDataStartPosition = $stream. Vị trí - 4
$stream. Seek($flacDataStartPosition, [System.IO.SeekOrigin]::Begin)
while (-not(ParseStreamInfoMetadataBlock($stream)))
{
$flacDataStartPosition = $flacDataStartPosition + 1
$stream. Seek($flacDataStartPosition, [System.IO.SeekOrigin]::Begin)
}
# Chèn mã bắt đầu
$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
}
-
Trên menu Tệp, bấm vào Lưu.
-
Trong hộp thoại Lưu Như, hãy định vị thư mục mà bạn muốn lưu tập lệnh PowerShell.
-
Trong hộp Tên tệp, nhập FixFlacFiles.ps1, thay đổi hộp Lưu dưới dạng thành Tài liệu Văn bản (*.txt) rồi bấm Lưu.
-
Trong trình Windows Explorer, hãy định vị tập lệnh PowerShell mà bạn đã lưu.
-
Bấm chuột phải vào tập lệnh rồi bấm Chạy với PowerShell.
-
Khi được nhắc, hãy nhập tên tệp của tệp FLAC không phát được, rồi nhấn Enter.