Add clip-id based Suno library sync
This commit is contained in:
+93
-5
@@ -1,6 +1,7 @@
|
||||
param(
|
||||
[int]$Port = 17873,
|
||||
[string]$OutputRoot = "\\VaultOfData\AKAMedia\음악\처리됨\SUNO",
|
||||
[string]$OutputRoot = "\\VaultOfData\AKAMedia\음악\처리됨",
|
||||
[string]$ArtistName = "SUNO",
|
||||
[string]$FfmpegPath = ""
|
||||
)
|
||||
|
||||
@@ -12,6 +13,21 @@ $inbox = Join-Path $scriptRoot "companion-inbox"
|
||||
$logs = Join-Path $scriptRoot "companion-logs"
|
||||
New-Item -ItemType Directory -Force -Path $inbox, $logs | Out-Null
|
||||
|
||||
function Resolve-LibraryRoot {
|
||||
param(
|
||||
[string]$Root,
|
||||
[string]$Artist
|
||||
)
|
||||
|
||||
$trimmed = $Root.TrimEnd("\", "/")
|
||||
if ((Split-Path -Leaf $trimmed) -ieq $Artist) {
|
||||
return $trimmed
|
||||
}
|
||||
return Join-Path $trimmed $Artist
|
||||
}
|
||||
|
||||
$libraryRoot = Resolve-LibraryRoot $OutputRoot $ArtistName
|
||||
|
||||
function Write-Response {
|
||||
param(
|
||||
[System.Net.Sockets.NetworkStream]$Stream,
|
||||
@@ -103,13 +119,16 @@ function Start-SunoProcess {
|
||||
"-ExecutionPolicy", "Bypass",
|
||||
"-File", $processor,
|
||||
"-ManifestPath", $ManifestPath,
|
||||
"-OutputRoot", $OutputRoot
|
||||
"-OutputRoot", $OutputRoot,
|
||||
"-ArtistName", $ArtistName
|
||||
)
|
||||
if ($FfmpegPath) {
|
||||
$args += @("-FfmpegPath", $FfmpegPath)
|
||||
}
|
||||
|
||||
$process = Start-Process -FilePath "powershell.exe" -ArgumentList $args -PassThru -NoNewWindow -RedirectStandardOutput $stdout -RedirectStandardError $stderr
|
||||
$shellPath = (Get-Process -Id $PID).Path
|
||||
if (-not $shellPath) { $shellPath = "pwsh.exe" }
|
||||
$process = Start-Process -FilePath $shellPath -ArgumentList $args -PassThru -NoNewWindow -RedirectStandardOutput $stdout -RedirectStandardError $stderr
|
||||
return [pscustomobject]@{
|
||||
jobId = $jobId
|
||||
pid = $process.Id
|
||||
@@ -118,6 +137,44 @@ function Start-SunoProcess {
|
||||
}
|
||||
}
|
||||
|
||||
function Get-ExistingSunoIds {
|
||||
param([string]$Root)
|
||||
|
||||
$ids = [System.Collections.Generic.HashSet[string]]::new()
|
||||
if (-not (Test-Path -LiteralPath $Root)) {
|
||||
return ,$ids
|
||||
}
|
||||
|
||||
Get-ChildItem -LiteralPath $Root -Recurse -Filter "*metadata.json" -File -ErrorAction SilentlyContinue | ForEach-Object {
|
||||
try {
|
||||
$json = Get-Content -LiteralPath $_.FullName -Raw | ConvertFrom-Json
|
||||
$id = "$($json.id)".Trim()
|
||||
if ($id) { [void]$ids.Add($id) }
|
||||
} catch {}
|
||||
}
|
||||
|
||||
return ,$ids
|
||||
}
|
||||
|
||||
function Get-MissingTracks {
|
||||
param($Tracks)
|
||||
|
||||
$existingIds = Get-ExistingSunoIds $libraryRoot
|
||||
$missing = @()
|
||||
foreach ($track in @($Tracks)) {
|
||||
$id = "$($track.id)".Trim()
|
||||
if (-not $id) { continue }
|
||||
if (-not $existingIds.Contains($id)) {
|
||||
$missing += $track
|
||||
}
|
||||
}
|
||||
|
||||
return [pscustomobject]@{
|
||||
existingIds = @($existingIds)
|
||||
missing = $missing
|
||||
}
|
||||
}
|
||||
|
||||
if (-not (Test-Path -LiteralPath $processor)) {
|
||||
throw "processor not found: $processor"
|
||||
}
|
||||
@@ -127,6 +184,7 @@ $listener.Start()
|
||||
|
||||
Write-Host "SUNO companion listening on http://127.0.0.1:$Port"
|
||||
Write-Host "OutputRoot: $OutputRoot"
|
||||
Write-Host "Library: $libraryRoot"
|
||||
Write-Host "Logs: $logs"
|
||||
Write-Host "Press Ctrl+C to stop."
|
||||
|
||||
@@ -144,7 +202,24 @@ try {
|
||||
|
||||
if ($request.Method -eq "GET" -and $request.Path -eq "/health") {
|
||||
Write-Host "Health check OK: $(Get-Date -Format 'HH:mm:ss')"
|
||||
Write-Response $stream 200 "OK" (@{ ok = $true; outputRoot = $OutputRoot } | ConvertTo-Json -Compress)
|
||||
Write-Response $stream 200 "OK" (@{ ok = $true; outputRoot = $OutputRoot; libraryRoot = $libraryRoot; artist = $ArtistName } | ConvertTo-Json -Compress)
|
||||
continue
|
||||
}
|
||||
|
||||
if ($request.Method -eq "POST" -and $request.Path -eq "/sync-index") {
|
||||
$manifest = $request.Body | ConvertFrom-Json
|
||||
$result = Get-MissingTracks $manifest.tracks
|
||||
Write-Host "Sync check: $(@($manifest.tracks).Count) received, $(@($result.missing).Count) missing"
|
||||
Write-Response $stream 200 "OK" (@{
|
||||
ok = $true
|
||||
outputRoot = $OutputRoot
|
||||
libraryRoot = $libraryRoot
|
||||
artist = $ArtistName
|
||||
received = @($manifest.tracks).Count
|
||||
existing = @($result.existingIds).Count
|
||||
missing = @($result.missing).Count
|
||||
tracks = @($result.missing)
|
||||
} | ConvertTo-Json -Depth 50 -Compress)
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -155,8 +230,21 @@ try {
|
||||
continue
|
||||
}
|
||||
|
||||
$sync = Get-MissingTracks $manifest.tracks
|
||||
$manifest.tracks = @($sync.missing)
|
||||
$manifest.count = @($manifest.tracks).Count
|
||||
if ($manifest.count -eq 0) {
|
||||
Write-Host "Process skipped: library already synced"
|
||||
Write-Response $stream 200 "OK" (@{
|
||||
ok = $true
|
||||
skipped = $true
|
||||
message = "library already synced"
|
||||
} | ConvertTo-Json -Compress)
|
||||
continue
|
||||
}
|
||||
|
||||
$manifestPath = Join-Path $inbox ("suno-library-{0}.manifest.json" -f (Get-Date -Format "yyyyMMdd-HHmmss"))
|
||||
$request.Body | Set-Content -LiteralPath $manifestPath -Encoding UTF8
|
||||
$manifest | ConvertTo-Json -Depth 50 | Set-Content -LiteralPath $manifestPath -Encoding UTF8
|
||||
$job = Start-SunoProcess $manifestPath
|
||||
|
||||
Write-Host "Started job $($job.jobId) for $(@($manifest.tracks).Count) tracks"
|
||||
|
||||
Reference in New Issue
Block a user