Skip to content

Instantly share code, notes, and snippets.

@milnak
Last active June 17, 2025 23:07
Show Gist options
  • Save milnak/812c7b2ac2ac584fb3aa5f438003514a to your computer and use it in GitHub Desktop.
Save milnak/812c7b2ac2ac584fb3aa5f438003514a to your computer and use it in GitHub Desktop.
Extract MuseScore score and parts to PDF
<#
.SYNOPSIS
Convert MuseScore file to PDF. Files are output to current folder.
.EXAMPLE
mkdir PDF; cd PDF
Get-ChildItem -File -LiteralPath '..' -Filter '*.mscz' | ForEach-Object { ConvertFrom-MuseScore -Extract Parts -File $_.FullName }
#>
function ConvertFrom-MuseScore {
param(
# Path to .mscz file
[Parameter(Mandatory)][string]$File,
# What to extract
[ValidateSet('Score', 'ScoreAndParts', 'ScoreAudio', 'Parts', IgnoreCase)]
[string[]]$Extract = @('Score', 'Parts'),
# Path to MuseScore. Defaults to standard install location.
[string]$MuseScorePath = (Join-Path "$env:ProgramFiles" 'MuseScore 4\bin\MuseScore4.exe')
)
# https://github.com/musescore/MuseScore/issues/22887
# --export-score-parts / -P CLI options no longer work in 4.x #22887
$path = Resolve-Path -LiteralPath $File
Write-Host ('Processing "{0}"...' -f (Split-Path -Path $path -Leaf))
Write-Host '* Extracting JSON'
$musescoreJsonFile = 'musescore-score-parts.json'
$process = Start-Process -Wait -NoNewWindow -PassThru `
-WorkingDirectory (Get-Location).Path `
-FilePath """$MuseScorePath""" `
-ArgumentList '--score-parts-pdf', """$path""", '--export-to', """$musescoreJsonFile"""
if ($process.ExitCode -ne 0) {
Write-Warning "ExitCode=$($process.ExitCode)"
}
$musescoreJson = Get-Content $musescoreJsonFile | ConvertFrom-Json
$name = Split-Path -LeafBase $musescoreJson.score
if ('ScoreAndParts' -in $Extract) {
# --score-parts-pdf CLI option outputs double base64-encoded JSON string for .scoreFullBin field #28436
# https://github.com/musescore/MuseScore/issues/28436
$filename = $name + ' [Score and Parts].pdf'
Write-Host "* Extracting score and parts ""$filename"""
$base64string = [Text.Encoding]::UTF8.GetString([Convert]::FromBase64String($musescoreJson.scoreFullBin))
Set-Content -LiteralPath $filename -AsByteStream -Value ([Convert]::FromBase64String($base64string))
}
if ('Score' -in $Extract) {
$filename = $name + ' [Score].pdf'
Write-Host "* Extracting score ""$filename"""
Set-Content -LiteralPath $filename -AsByteStream -Value ([Convert]::FromBase64String($musescoreJson.scoreBin))
}
if ('Parts' -in $Extract) {
for ($i = 0; $i -lt $musescoreJson.parts.Count; $i++) {
$partname = $musescoreJson.parts[$i]
$filename = '{0} [{1}].pdf' -f (Split-Path -LeafBase $name), $partname
Write-Host "* Extracting part ""$filename"""
Set-Content -LiteralPath $filename -AsByteStream -Value ([Convert]::FromBase64String($musescoreJson.partsBin[$i]))
}
}
Remove-Item -LiteralPath $musescoreJsonFile
if ('ScoreAudio' -in $Extract) {
$filename = $name + '.mp3'
Write-Host "* Extracting audio ""$filename""..."
$process = Start-Process -Wait -NoNewWindow -PassThru `
-WorkingDirectory (Get-Location).Path `
-FilePath """$MuseScorePath""" `
-ArgumentList """$path""", '--export-to', """$filename"""
if ($process.ExitCode -ne 0) {
Write-Warning "ExitCode=$($process.ExitCode)"
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment