Improve Suno WAV URL queue detection
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
// ==UserScript==
|
// ==UserScript==
|
||||||
// @name ChatGPT to Suno Prompt Copier
|
// @name ChatGPT to Suno Prompt Copier
|
||||||
// @namespace local.suno-helper
|
// @namespace local.suno-helper
|
||||||
// @version 0.7.1
|
// @version 0.7.2
|
||||||
// @description Copy structured ChatGPT song prompt versions into Suno fields.
|
// @description Copy structured ChatGPT song prompt versions into Suno fields.
|
||||||
// @author local
|
// @author local
|
||||||
// @match https://chatgpt.com/*
|
// @match https://chatgpt.com/*
|
||||||
@@ -835,8 +835,51 @@
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function extractWavUrl(value) {
|
||||||
|
if (!value) return "";
|
||||||
|
if (typeof value === "string") {
|
||||||
|
const direct = value.match(/https?:\/\/[^"' <>)]+?\.wav(?:\?[^"' <>)]+)?/i)?.[0] || "";
|
||||||
|
if (direct) return normalizeSunoMediaUrl(direct);
|
||||||
|
return /\.wav(?:\?|$)/i.test(value) ? normalizeSunoMediaUrl(value) : "";
|
||||||
|
}
|
||||||
|
if (Array.isArray(value)) {
|
||||||
|
for (const item of value) {
|
||||||
|
const found = extractWavUrl(item);
|
||||||
|
if (found) return found;
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
if (typeof value === "object") {
|
||||||
|
const directKeys = [
|
||||||
|
"url",
|
||||||
|
"download_url",
|
||||||
|
"downloadUrl",
|
||||||
|
"wav_url",
|
||||||
|
"wavUrl",
|
||||||
|
"wav_file_url",
|
||||||
|
"wavFileUrl",
|
||||||
|
"file_url",
|
||||||
|
"fileUrl",
|
||||||
|
"signed_url",
|
||||||
|
"signedUrl",
|
||||||
|
"audio_url",
|
||||||
|
"audioUrl",
|
||||||
|
"file",
|
||||||
|
];
|
||||||
|
for (const key of directKeys) {
|
||||||
|
const found = extractWavUrl(value[key]);
|
||||||
|
if (found) return found;
|
||||||
|
}
|
||||||
|
for (const item of Object.values(value)) {
|
||||||
|
const found = extractWavUrl(item);
|
||||||
|
if (found) return found;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
async function requestSunoWavUrl(track) {
|
async function requestSunoWavUrl(track) {
|
||||||
if (!track.id) return track.wavUrl || "";
|
if (!track.id) return extractWavUrl(track.wavUrl);
|
||||||
const base = `https://studio-api-prod.suno.com/api/gen/${encodeURIComponent(track.id)}`;
|
const base = `https://studio-api-prod.suno.com/api/gen/${encodeURIComponent(track.id)}`;
|
||||||
try {
|
try {
|
||||||
await callSunoJson(`${base}/convert_wav/`, { method: "POST" });
|
await callSunoJson(`${base}/convert_wav/`, { method: "POST" });
|
||||||
@@ -844,24 +887,18 @@
|
|||||||
console.warn("[ChatGPT to Suno] convert_wav failed", error);
|
console.warn("[ChatGPT to Suno] convert_wav failed", error);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let attempt = 0; attempt < 8; attempt += 1) {
|
for (let attempt = 0; attempt < 20; attempt += 1) {
|
||||||
try {
|
try {
|
||||||
const data = await callSunoJson(`${base}/wav_file/`, { method: "GET" });
|
const data = await callSunoJson(`${base}/wav_file/`, { method: "GET" });
|
||||||
const direct =
|
const direct = extractWavUrl(data);
|
||||||
data?.url ||
|
if (direct) return direct;
|
||||||
data?.download_url ||
|
|
||||||
data?.wav_url ||
|
|
||||||
data?.audio_url ||
|
|
||||||
data?.file ||
|
|
||||||
(typeof data === "string" && /^https?:\/\//i.test(data) ? data : "");
|
|
||||||
if (direct) return normalizeSunoMediaUrl(direct);
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.warn("[ChatGPT to Suno] wav_file failed", error);
|
console.warn("[ChatGPT to Suno] wav_file failed", error);
|
||||||
}
|
}
|
||||||
await new Promise((resolve) => setTimeout(resolve, 1300));
|
await new Promise((resolve) => setTimeout(resolve, 1500));
|
||||||
}
|
}
|
||||||
|
|
||||||
return track.wavUrl || "";
|
return extractWavUrl(track.wavUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
function downloadTextFile(text, name) {
|
function downloadTextFile(text, name) {
|
||||||
@@ -980,12 +1017,14 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
let enqueued = 0;
|
let enqueued = 0;
|
||||||
|
let wavPending = 0;
|
||||||
for (let index = 0; index < missingTracks.length; index += 1) {
|
for (let index = 0; index < missingTracks.length; index += 1) {
|
||||||
const track = { ...missingTracks[index] };
|
const track = { ...missingTracks[index] };
|
||||||
setStatus(statusTarget, `${index + 1}/${missingTracks.length} 없는 곡 WAV 준비 중: ${track.title || track.id}`);
|
setStatus(statusTarget, `${index + 1}/${missingTracks.length} 없는 곡 WAV 준비 중: ${track.title || track.id}`);
|
||||||
track.wavUrl = await requestSunoWavUrl(track);
|
track.wavUrl = await requestSunoWavUrl(track);
|
||||||
if (!track.wavUrl) {
|
if (!track.wavUrl) {
|
||||||
setStatus(statusTarget, `${track.title || track.id} WAV 변환 URL이 아직 안 나와서 큐에 넣지 않음`);
|
wavPending += 1;
|
||||||
|
setStatus(statusTarget, `${track.title || track.id} WAV 변환 URL이 아직 안 나와서 보류 (${wavPending}곡)`);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const enqueueManifest = {
|
const enqueueManifest = {
|
||||||
@@ -1007,7 +1046,11 @@
|
|||||||
const data = tryParseJson(text) || {};
|
const data = tryParseJson(text) || {};
|
||||||
setStatus(statusTarget, `${enqueued}/${missingTracks.length}곡 큐 추가: ${track.title || track.id} / 대기 ${data.queued ?? "?"}개`);
|
setStatus(statusTarget, `${enqueued}/${missingTracks.length}곡 큐 추가: ${track.title || track.id} / 대기 ${data.queued ?? "?"}개`);
|
||||||
}
|
}
|
||||||
setStatus(statusTarget, `큐 전송 완료: 새 곡 ${enqueued}개. 로컬 프로그램이 순서대로 처리 중.`);
|
if (!enqueued) {
|
||||||
|
setStatus(statusTarget, `큐에 넣은 곡 없음. 새 곡 ${missingTracks.length}개 중 ${wavPending}개가 아직 SUNO WAV 변환 URL을 안 줬어.`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setStatus(statusTarget, `큐 전송 완료: 새 곡 ${enqueued}개, WAV 보류 ${wavPending}개. 로컬 프로그램이 순서대로 처리 중.`);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function testCompanion(statusTarget) {
|
async function testCompanion(statusTarget) {
|
||||||
|
|||||||
Reference in New Issue
Block a user