zenjoul80 commited on
Commit
15d2375
·
verified ·
1 Parent(s): ad31a8a

Update templates/index.html

Browse files
Files changed (1) hide show
  1. templates/index.html +199 -74
templates/index.html CHANGED
@@ -1,92 +1,217 @@
1
  <!DOCTYPE html>
2
- <html>
3
  <head>
4
- <title>Suno Custom Cover Studio</title>
5
- <link rel="stylesheet" href="/static/style.css">
 
6
  <script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.0.1/socket.io.js"></script>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7
  </head>
8
  <body>
9
- <div class="box">
10
- <div style="display:flex; justify-content:space-between; align-items:center;">
11
- <h2>Suno AI Cover</h2>
12
- <div style="color:#f59e0b">Credits: <span id="cr">?</span></div>
13
- </div>
14
 
15
- <div class="grid-input" style="margin-top:20px;">
16
- <input type="password" id="tk" placeholder="Paste Suno API Token (sk-...)">
17
- <button onclick="saveTk()" style="background:#334155;">Connect Token</button>
18
- </div>
 
19
 
20
- <hr style="border:0.5px solid #334155; margin:20px 0;">
21
-
22
- <div class="grid-input">
23
- <div>
24
- <label>Model</label>
25
- <select id="mdl">
26
- <option value="V5">V5 (Recommended)</option>
27
- <option value="V4_5ALL">V4_5ALL (Max 1 min audio)</option>
28
- <option value="V4_5PLUS">V4_5PLUS</option>
29
- <option value="V4">V4</option>
30
- </select>
31
- </div>
32
- <div>
33
- <label>Audio URL</label>
34
- <input type="text" id="url" placeholder="Direct .mp3 link">
35
- </div>
36
- <div>
37
- <label>Style/Genre</label>
38
- <input type="text" id="style" placeholder="e.g. Jazz, Pop, 120BPM">
39
- </div>
40
- <div>
41
- <label>Title</label>
42
- <input type="text" id="title" placeholder="Song Title">
43
- </div>
44
- <div class="full-width">
45
- <label>Lyrics (Prompt)</label>
46
- <textarea id="lyr" placeholder="Enter lyrics here (Custom Mode)..."></textarea>
47
  </div>
48
  </div>
 
49
 
50
- <div style="margin-bottom:15px;">
51
- <input type="checkbox" id="instr" style="width:auto;"> Instrumental Mode
52
- </div>
53
 
54
- <button onclick="go()" style="width:100%;">Generate New Cover</button>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
55
 
56
- <div id="log">Ready for task...</div>
57
- <a id="dl" href="#" target="_blank" class="dl-btn">Download Finished Track</a>
 
 
58
  </div>
59
 
60
- <script>
61
- const socket = io();
62
- const log = document.getElementById('log');
63
-
64
- function saveTk() { socket.emit('save_token', {token: document.getElementById('tk').value}); }
65
-
66
- function go() {
67
- const payload = {
68
- uploadUrl: document.getElementById('url').value,
69
- model: document.getElementById('mdl').value,
70
- style: document.getElementById('style').value,
71
- title: document.getElementById('title').value || "Cover Track",
72
- prompt: document.getElementById('lyr').value,
73
- instrumental: document.getElementById('instr').checked,
74
- customMode: true,
75
- callBackUrl: "https://example.com/callback" // Placeholder
76
- };
77
- socket.emit('start_gen', payload);
78
- document.getElementById('dl').style.display = 'none';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
79
  }
 
 
80
 
81
- socket.on('credits', d => document.getElementById('cr').innerText = d.val);
82
- socket.on('status', d => {
83
- log.innerHTML += `<div>[${new Date().toLocaleTimeString()}] ${d.msg}</div>`;
84
- log.scrollTop = log.scrollHeight;
85
- if(d.done) {
86
- document.getElementById('dl').href = d.url;
87
- document.getElementById('dl').style.display = 'block';
88
- }
89
- });
90
- </script>
91
  </body>
92
  </html>
 
1
  <!DOCTYPE html>
2
+ <html lang="en">
3
  <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Suno Custom Studio 2026</title>
7
  <script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.0.1/socket.io.js"></script>
8
+ <style>
9
+ /* Responsive CSS */
10
+ :root {
11
+ --primary: #6366f1;
12
+ --bg: #0b0e14;
13
+ --card: #151921;
14
+ --input: #1c222d;
15
+ --text: #f8fafc;
16
+ --accent: #10b981;
17
+ }
18
+
19
+ body {
20
+ font-family: 'Inter', sans-serif;
21
+ background: var(--bg);
22
+ color: var(--text);
23
+ margin: 0;
24
+ padding: 15px;
25
+ display: flex;
26
+ justify-content: center;
27
+ }
28
+
29
+ .box {
30
+ width: 100%;
31
+ max-width: 700px;
32
+ background: var(--card);
33
+ padding: 25px;
34
+ border-radius: 16px;
35
+ box-shadow: 0 10px 30px rgba(0,0,0,0.5);
36
+ }
37
+
38
+ .header {
39
+ display: flex;
40
+ justify-content: space-between;
41
+ align-items: center;
42
+ margin-bottom: 20px;
43
+ }
44
+
45
+ .grid {
46
+ display: grid;
47
+ grid-template-columns: 1fr;
48
+ gap: 15px;
49
+ }
50
+
51
+ @media (min-width: 600px) {
52
+ .grid { grid-template-columns: 1fr 1fr; }
53
+ .full { grid-column: span 2; }
54
+ }
55
+
56
+ label { font-size: 0.8rem; color: #718096; margin-bottom: 5px; display: block; }
57
+ input, select, textarea {
58
+ width: 100%;
59
+ padding: 12px;
60
+ background: var(--input);
61
+ border: 1px solid #2d3748;
62
+ border-radius: 8px;
63
+ color: white;
64
+ font-size: 16px;
65
+ box-sizing: border-box;
66
+ }
67
+
68
+ textarea { min-height: 120px; resize: vertical; }
69
+
70
+ button {
71
+ width: 100%;
72
+ padding: 15px;
73
+ background: var(--primary);
74
+ border: none;
75
+ color: white;
76
+ font-weight: bold;
77
+ border-radius: 8px;
78
+ cursor: pointer;
79
+ margin-top: 20px;
80
+ }
81
+
82
+ button:hover { filter: brightness(1.1); }
83
+
84
+ #log {
85
+ margin-top: 20px;
86
+ background: #000;
87
+ padding: 15px;
88
+ border-radius: 8px;
89
+ font-family: monospace;
90
+ font-size: 13px;
91
+ color: #94a3b8;
92
+ height: 120px;
93
+ overflow-y: auto;
94
+ border: 1px solid #222;
95
+ }
96
+
97
+ .dl-link {
98
+ display: none;
99
+ text-decoration: none;
100
+ background: var(--accent);
101
+ color: white;
102
+ text-align: center;
103
+ padding: 15px;
104
+ border-radius: 8px;
105
+ font-weight: bold;
106
+ margin-top: 15px;
107
+ }
108
+ </style>
109
  </head>
110
  <body>
 
 
 
 
 
111
 
112
+ <div class="box">
113
+ <div class="header">
114
+ <h2 style="margin:0;">Suno Studio</h2>
115
+ <div style="color:#f59e0b">Credits: <span id="cr">?</span></div>
116
+ </div>
117
 
118
+ <div class="grid">
119
+ <div class="full">
120
+ <label>API Token</label>
121
+ <div style="display:flex; gap:10px;">
122
+ <input type="password" id="tk" placeholder="sk-...">
123
+ <button onclick="saveTk()" style="margin:0; width:auto;">Connect</button>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
124
  </div>
125
  </div>
126
+ </div>
127
 
128
+ <hr style="border:0.5px solid #2d3748; margin:25px 0;">
 
 
129
 
130
+ <div class="grid">
131
+ <div>
132
+ <label>Model Version</label>
133
+ <select id="mdl">
134
+ <option value="V5">V5 (Latest)</option>
135
+ <option value="V4_5ALL">V4_5ALL</option>
136
+ <option value="V4">V4</option>
137
+ </select>
138
+ </div>
139
+ <div>
140
+ <label>Source MP3 URL</label>
141
+ <input type="text" id="url" placeholder="https://...">
142
+ </div>
143
+ <div>
144
+ <label>Music Style (Genre/Mood)</label>
145
+ <input type="text" id="style" placeholder="e.g. unplugged, female voice">
146
+ </div>
147
+ <div>
148
+ <label>Song Title</label>
149
+ <input type="text" id="title" placeholder="My Creation">
150
+ </div>
151
+ <div class="full">
152
+ <label>Lyrics (Custom Mode)</label>
153
+ <textarea id="lyr" placeholder="[Verse 1]... [Chorus]..."></textarea>
154
+ </div>
155
+ </div>
156
 
157
+ <div style="margin-top:15px;">
158
+ <label style="display:inline; cursor:pointer;">
159
+ <input type="checkbox" id="instr" style="width:auto;"> Instrumental Only
160
+ </label>
161
  </div>
162
 
163
+ <button onclick="generate()">Start Generation</button>
164
+
165
+ <div id="log">Logs: Ready for input.</div>
166
+
167
+ <a id="dl" href="#" target="_blank" class="dl-link">📥 Download Generated Track</a>
168
+ </div>
169
+
170
+ <script>
171
+ const socket = io();
172
+ const log = document.getElementById('log');
173
+
174
+ function saveTk() {
175
+ socket.emit('save_token', {token: document.getElementById('tk').value});
176
+ }
177
+
178
+ function generate() {
179
+ const payload = {
180
+ uploadUrl: document.getElementById('url').value,
181
+ customMode: true,
182
+ instrumental: document.getElementById('instr').checked,
183
+ model: document.getElementById('mdl').value,
184
+ prompt: document.getElementById('lyr').value,
185
+ style: document.getElementById('style').value,
186
+ title: document.getElementById('title').value || "Suno_Track",
187
+ // Note: callBackUrl is set in app.py logic
188
+ };
189
+
190
+ socket.emit('start_gen', payload);
191
+ document.getElementById('dl').style.display = 'none';
192
+ addLog("Sending payload to Suno...");
193
+ }
194
+
195
+ function addLog(msg) {
196
+ log.innerHTML += `<div>[${new Date().toLocaleTimeString()}] ${msg}</div>`;
197
+ log.scrollTop = log.scrollHeight;
198
+ }
199
+
200
+ socket.on('credits', d => document.getElementById('cr').innerText = d.val);
201
+
202
+ socket.on('status', d => {
203
+ addLog(d.msg);
204
+ if (d.done && d.url) {
205
+ // Pointing to the Flask Proxy Route
206
+ const encodedUrl = encodeURIComponent(d.url);
207
+ const title = encodeURIComponent(document.getElementById('title').value || "Track");
208
+
209
+ const dlBtn = document.getElementById('dl');
210
+ dlBtn.href = `/download_proxy?url=${encodedUrl}&title=${title}`;
211
+ dlBtn.style.display = 'block';
212
  }
213
+ });
214
+ </script>
215
 
 
 
 
 
 
 
 
 
 
 
216
  </body>
217
  </html>