Expose Suno MP3 candidate diagnostics

This commit is contained in:
DESKTOP-KSVGT20\shkim
2026-05-02 00:58:15 +09:00
parent cc9399c37f
commit dbfbd85576
+38 -3
View File
@@ -1,7 +1,7 @@
// ==UserScript==
// @name ChatGPT to Suno Prompt Copier
// @namespace local.suno-helper
// @version 0.8.1
// @version 0.8.2
// @description Copy structured ChatGPT song prompt versions into Suno fields.
// @author local
// @match https://chatgpt.com/*
@@ -28,7 +28,7 @@
(function () {
"use strict";
const SCRIPT_VERSION = "0.8.1";
const SCRIPT_VERSION = "0.8.2";
const STORAGE_KEY = "chatgptSunoPromptSlots";
const SLOT_COUNT = 2;
const isChatGPT = location.hostname.includes("chatgpt.com") || location.hostname.includes("chat.openai.com");
@@ -551,6 +551,30 @@
return unique([...String(text || "").matchAll(pattern)].map((match) => match[0].replace(/\\u002F/g, "/")));
}
function collectStringValues(value, output = []) {
if (value == null) return output;
if (typeof value === "string") {
output.push(value);
return output;
}
if (Array.isArray(value)) {
for (const item of value) collectStringValues(item, output);
return output;
}
if (typeof value === "object") {
for (const item of Object.values(value)) collectStringValues(item, output);
}
return output;
}
function extractAudioUrlsFromValue(value) {
const text = collectStringValues(value).join("\n");
return unique([
...extractUrls(text, /https?:\\?\/\\?\/cdn[0-9]*\.suno\.ai\\?\/[^"' <>)]+?\.(?:mp3|m4a|oga|ogg)(?:\?[^"' <>)]+)?/gi),
...extractUrls(text, /https?:\/\/[^"' <>)]+?\.(?:mp3|m4a|oga|ogg)(?:\?[^"' <>)]+)?/gi),
].map((url) => normalizeSunoMediaUrl(url.replace(/\\\//g, "/"))));
}
function readJsonScripts() {
const results = [];
for (const script of document.querySelectorAll("script")) {
@@ -604,7 +628,8 @@
const title = String(firstValue(object, ["title", "name"]) || id || "suno-track").trim();
const imageUrl = firstValue(object, ["image_url", "imageUrl", "image_large_url", "imageLargeUrl", "cover_url", "coverUrl"]);
const audioPath = firstValue(object, ["audio_url", "audioUrl", "stream_audio_url", "streamAudioUrl", "play_url", "playUrl", "play_path", "playPath", "mp3_url", "mp3Url", "video_url", "videoUrl"]);
const audioUrl = normalizeSunoMediaUrl(audioPath);
const audioUrls = extractAudioUrlsFromValue(object);
const audioUrl = normalizeSunoMediaUrl(audioPath) || audioUrls[0] || "";
const wavPath = firstValue(object, ["wav_url", "wavUrl", "download_url", "downloadUrl"]);
const wavUrl = normalizeSunoMediaUrl(wavPath);
const lyrics = firstValue(object, ["prompt", "lyrics", "lyric", "text"]);
@@ -624,6 +649,7 @@
createdAt,
owner: owner || ownerFromUser,
audioUrl,
detectedAudioUrls: audioUrls,
wavUrl,
imageUrl,
pageUrl: location.href,
@@ -637,6 +663,7 @@
for (const key of ["title", "lyrics", "style", "model", "createdAt", "audioUrl", "wavUrl", "imageUrl", "pageUrl"]) {
if (!target[key] && source[key]) target[key] = source[key];
}
target.detectedAudioUrls = unique([...(target.detectedAudioUrls || []), ...(source.detectedAudioUrls || [])]);
target.metadata = target.metadata && Object.keys(target.metadata).length ? target.metadata : source.metadata;
return target;
}
@@ -1098,7 +1125,13 @@
function getMp3Candidates(track) {
const candidates = [];
if (track.audioUrl && !/\.wav(?:\?|$)/i.test(track.audioUrl)) candidates.push(track.audioUrl);
for (const url of track.detectedAudioUrls || []) {
if (url && !/\.wav(?:\?|$)/i.test(url)) candidates.push(url);
}
const metadata = track.metadata || {};
for (const url of extractAudioUrlsFromValue(metadata)) {
if (url && !/\.wav(?:\?|$)/i.test(url)) candidates.push(url);
}
for (const value of [
metadata.audio_url,
metadata.audioUrl,
@@ -1556,9 +1589,11 @@
selectedTrack: selectedTrack ? {
id: selectedTrack.id || "",
title: selectedTrack.title || "",
audioUrl: selectedTrack.audioUrl || "",
hasWavUrl: Boolean(selectedTrack.wavUrl),
hasImageUrl: Boolean(selectedTrack.imageUrl),
hasLyrics: Boolean(selectedTrack.lyrics),
mp3Candidates: getMp3Candidates(selectedTrack).slice(0, 10),
} : null,
capturedSunoResponses: capturedSunoResponses.length,
companion: healthError ? { ok: false, error: healthError } : health,