บทสรุป
การอัปเดตนี้แก้ไขปัญหาการเข้ารหัสเมตาดาต้าที่ทําให้ไฟล์เพลง Free Lossless Audio Codec (FLAC) ไม่สามารถเล่นได้หากชื่อ ศิลปิน หรือเมตาดาต้าอื่นๆ มีการเปลี่ยนแปลง
สาเหตุ
ปัญหานี้อาจเกิดขึ้นเมื่อไฟล์ FLAC มีเฟรม ID3 ก่อนส่วนหัว FLAC เฟรม ID3 ประกอบด้วยเมตาดาต้า เช่น ชื่อเรื่องและศิลปิน ตัวจัดการคุณสมบัติ FLAC ถือว่าไฟล์ FLAC ทั้งหมดเริ่มต้นด้วยรหัสเริ่มต้น 4 ไบต์ fLaC และไม่ได้คํานึงถึงเฟรม ID3 ที่จุดเริ่มต้นของไฟล์ ดังนั้นเฟรม ID3 จะถูกเขียนทับโดยไม่มีรหัสเริ่มต้น fLaC ที่แสดงไฟล์ที่ไม่สามารถเล่นได้
การแก้ปัญหา
เพื่อป้องกันปัญหานี้สําหรับไฟล์เพลง FLAC ในอนาคต ให้ติดตั้ง 25 พฤษภาคม 2021 KB5003214 (ระบบปฏิบัติการรุ่น 19041.1013, 19042.1013 และ 19043.1013) Preview
เมื่อต้องการซ่อมแซมไฟล์เพลง FLAC ที่ได้รับผลกระทบ ให้เรียกใช้สคริปต์ PowerShell ต่อไปนี้
สำคัญ
สคริปต์นี้จะไม่คืนค่าเมตาดาต้าที่หายไปซึ่งถูกจัดเก็บไว้ในเฟรม ID3 แต่จะทําให้สามารถเล่นไฟล์ได้อีกครั้ง
เปิดแผ่นจดบันทึก
คัดลอกและวางสคริปต์ต่อไปนี้ลงในแผ่นจดบันทึก:
# ลิขสิทธิ์ 2021 Microsoft
# สคริปต์นี้จะซ่อมแซมไฟล์ FLAC ที่เสียหายโดย Media Foundation ในการอ้างอิงถึง KB5003430
# โปรดดูที่ KB5003430 สําหรับข้อมูลเพิ่มเติม
param(
[parameter(Mandatory=$true,
HelpMessage="เส้นทางไปยังไฟล์ FLAC ที่ได้รับความเสียหายโดย Media Foundation"
ValueFromRemainingArguments=$true)]
[ValidateScript({ -not [String]::IsNullOrEmpty($_) -and (Test-Path $_) })]
[สตริง]$File
)
# เราจําเป็นต้องสํารองข้อมูลไฟล์ปัจจุบันในกรณีที่เรามีข้อผิดพลาดใดๆ
$FileDirectory = Split-Path -แก้ไข$File
$Filename = Split-Path -Leaf -Resolve $File
$FullPath = Join-Path -แก้ไข$FileDirectory $Filename
$Filename = [String]::Format("Backup_{0:yyyyMMdd_hhmmss}_{1}", [DateTime]::Now, $Filename)
$BackupLocation = Join-Path $FileDirectory $Filename
Write-Output "เครื่องมือซ่อมแซม Microsoft FLAC เครื่องมือนี้จะซ่อมแซมไฟล์เสียง FLAC ที่เสียหายเมื่อแก้ไขรายละเอียด"
Write-Output "ไฟล์ที่ได้รับผลกระทบ: $FullPath"
Write-Output "จะทําการสํารองข้อมูลของไฟล์: $BackupLocation"
Write-Output "คุณต้องการดําเนินการต่อหรือไม่"
$choice=$host.ui.PromptForChoice("แก้ไขสคริปต์ FLAC", "คุณต้องการดําเนินการต่อ" ('&ใช่', '&ไม่ใช่'), 1)
ฟังก์ชัน ParseStreamInfoMetadataBlock([System.IO.FileStream]$stream)
{
$blockType = $stream ReadByte()
$lastBlock = ($blockType -shr 7) -ne 0
$blockType = 0x7F $blockType
if ($blockType -ne 0)
{
ส่งคืน$false
}
$blockSize = (($stream. ReadByte() -shl 16) -bor ($stream. ReadByte() -shl 8) -bor $stream ReadByte())
if ($blockSize -lt 34)
{
ส่งคืน$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)
{
ส่งคืน$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 ไบต์[] 16
$stream อ่าน($MD 5HashBytes, 0, $MD 5HashBytes.Length)
$MD 5Hash = [Guid]($MD 5HashBytes)
if ($sampleRate -eq 0)
{
ส่งคืน$false
}
# ผ่านการตรวจสอบเหล่านี้หมายความว่าเราอาจมีส่วนหัวของข้อมูลสตรีมและสามารถสร้างไฟล์ใหม่ได้
Write-Output "ข้อมูล Stream ไฟล์"
Write-Output "อัตราตัวอย่าง: $sampleRate"
Write-Output "แชนเนลเสียง: $channelCount"
Write-Output "ความลึกของตัวอย่าง: $bitsPerSample"
Write-Output "แฮชตัวอย่างเสียง MD5: $MD 5Hash"
ส่งคืน$true
}
if ($choice -eq 0)
{
Copy-Item $FullPath -ปลายทาง $BackupLocation -Force
$stream = [System.IO.File]::Open($FullPath, [System.IO.FileMode]::Open)
$stream Seek(4, [System.IO.SeekOrigin]::Begin)
ในขณะที่ ($stream ReadByte() -eq 0) {}
# ตอนนี้เราต้องค้นหาว่าเฟรมเมตาของ FLAC ที่ถูกต้องเริ่มต้นที่ใด
# เราน่าจะชี้ไปที่ไบต์สุดท้ายของสมาชิกขนาด ดังนั้นเราจะย้อนกลับไป 4 ไบต์แล้วลองใหม่
$flacDataStartPosition = $stream ตําแหน่ง - 4
$stream Seek($flacDataStartPosition, [System.IO.SeekOrigin]::Begin)
ในขณะที่ (-not(ParseStreamInfoMetadataBlock($stream)))
{
$flacDataStartPosition = $flacDataStartPosition + 1
$stream Seek($flacDataStartPosition, [System.IO.SeekOrigin]::Begin)
}
# ใส่รหัสเริ่มต้น
$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 ปิด()
$fixedStream.Close()
$FullPath Move-Item -Force "$FullPath.tmp"
}ในเมนู ไฟล์ ให้คลิก บันทึก
ในกล่องโต้ตอบ บันทึกเป็น ให้ค้นหาโฟลเดอร์ที่คุณต้องการบันทึกสคริปต์ PowerShell
ในกล่อง ชื่อไฟล์ ให้พิมพ์ FixFlacFiles.ps1เปลี่ยนกล่อง บันทึกเป็นชนิด เป็น เอกสารข้อความ (*.txt) แล้วคลิก บันทึก
ใน Windows Explorer ให้ค้นหาสคริปต์ PowerShell ที่คุณบันทึกไว้
คลิกขวาที่สคริปต์ แล้วคลิก เรียกใช้ด้วย PowerShell
เมื่อได้รับพร้อมท์ ให้พิมพ์ชื่อไฟล์ของไฟล์ FLAC ที่ไม่สามารถเล่นได้ แล้วกด Enter