Spaces:
Runtime error
Runtime error
Update app.py
Browse files
app.py
CHANGED
|
@@ -13,108 +13,87 @@ import tempfile
|
|
| 13 |
|
| 14 |
from download import download_model
|
| 15 |
|
| 16 |
-
#
|
| 17 |
APP_DIR = op.dirname(op.abspath(__file__))
|
| 18 |
-
|
| 19 |
-
print("Successful downloaded model.")
|
| 20 |
|
| 21 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 22 |
from levo_inference import LeVoInference
|
| 23 |
-
|
| 24 |
|
| 25 |
EXAMPLE_LYRICS = """
|
| 26 |
[intro-medium]
|
| 27 |
|
| 28 |
[verse]
|
| 29 |
-
|
| 30 |
-
窗外风景急速倒退
|
| 31 |
-
像是与过去在告别
|
| 32 |
-
奔向未定的终点线
|
| 33 |
-
心中混杂期待恐惧
|
| 34 |
-
请别问我要去哪里
|
| 35 |
-
也别追问归期何时
|
| 36 |
-
|
| 37 |
-
[chorus]
|
| 38 |
-
让我随风去流浪
|
| 39 |
我不想停留原地
|
| 40 |
原地只有无尽循环
|
| 41 |
不再规划人生
|
| 42 |
不再遵循地图
|
| 43 |
-
我渴望一场意外之旅
|
| 44 |
-
邂逅未知的自己
|
| 45 |
-
|
| 46 |
-
[inst-short]
|
| 47 |
-
|
| 48 |
-
[verse]
|
| 49 |
-
行李简单只有背囊
|
| 50 |
-
装着一颗渴望自由的心
|
| 51 |
-
旧照片已撕碎抛洒
|
| 52 |
-
不要任何牵绊
|
| 53 |
-
不要沉重过往
|
| 54 |
|
| 55 |
[chorus]
|
| 56 |
让我随风去流浪
|
| 57 |
-
|
| 58 |
-
原地只会滋生腐朽
|
| 59 |
-
不再规划人生
|
| 60 |
-
不再遵循地图
|
| 61 |
-
我渴望一场灵魂蜕变
|
| 62 |
-
在路途中找到答案
|
| 63 |
-
|
| 64 |
-
[bridge]
|
| 65 |
-
山川湖海皆是导师
|
| 66 |
-
星空之下顿悟了渺小
|
| 67 |
-
狭隘的悲欢被风吹散
|
| 68 |
-
融入天地间的壮阔
|
| 69 |
-
|
| 70 |
-
[chorus]
|
| 71 |
-
它教会我何为生命
|
| 72 |
-
何为存在的意义
|
| 73 |
-
渺小如尘却也独特
|
| 74 |
-
勇敢地写下自己的诗
|
| 75 |
-
这是我的远征之路
|
| 76 |
生命最绚烂的章节
|
| 77 |
-
|
| 78 |
-
[outro-medium]
|
| 79 |
""".strip()
|
| 80 |
|
| 81 |
-
|
| 82 |
-
|
| 83 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 84 |
|
| 85 |
def save_as_flac(sample_rate, audio_data):
|
| 86 |
if isinstance(audio_data, tuple):
|
| 87 |
sample_rate, audio_data = audio_data
|
| 88 |
-
|
| 89 |
if audio_data.dtype == np.float64:
|
| 90 |
audio_data = audio_data.astype(np.float32)
|
| 91 |
-
|
| 92 |
temp_file = tempfile.NamedTemporaryFile(delete=False, suffix=".flac")
|
| 93 |
sf.write(temp_file, audio_data, sample_rate, format='FLAC')
|
| 94 |
return temp_file.name
|
| 95 |
|
| 96 |
-
|
| 97 |
-
# 模拟歌曲生成函数
|
| 98 |
def generate_song(lyric, description=None, prompt_audio=None, genre=None, cfg_coef=None, temperature=0.1, top_k=-1, gen_type="mixed", progress=gr.Progress(track_tqdm=True)):
|
| 99 |
global MODEL
|
| 100 |
global STRUCTS
|
| 101 |
-
|
| 102 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 103 |
vocal_structs = ['[verse]', '[chorus]', '[bridge]']
|
| 104 |
sample_rate = MODEL.cfg.sample_rate
|
| 105 |
|
| 106 |
-
#
|
| 107 |
lyric = lyric.replace("[intro]", "[intro-short]").replace("[inst]", "[inst-short]").replace("[outro]", "[outro-short]")
|
| 108 |
paragraphs = [p.strip() for p in lyric.strip().split('\n\n') if p.strip()]
|
|
|
|
| 109 |
if len(paragraphs) < 1:
|
| 110 |
return None, json.dumps("Lyrics can not be left blank")
|
|
|
|
| 111 |
paragraphs_norm = []
|
| 112 |
vocal_flag = False
|
|
|
|
| 113 |
for para in paragraphs:
|
| 114 |
lines = para.splitlines()
|
| 115 |
struct_tag = lines[0].strip().lower()
|
|
|
|
| 116 |
if struct_tag not in STRUCTS:
|
| 117 |
return None, json.dumps(f"Segments should start with a structure tag in {STRUCTS}")
|
|
|
|
| 118 |
if struct_tag in vocal_structs:
|
| 119 |
vocal_flag = True
|
| 120 |
if len(lines) < 2 or not [line.strip() for line in lines[1:] if line.strip()]:
|
|
@@ -130,11 +109,12 @@ def generate_song(lyric, description=None, prompt_audio=None, genre=None, cfg_co
|
|
| 130 |
else:
|
| 131 |
new_para_str = struct_tag
|
| 132 |
paragraphs_norm.append(new_para_str)
|
|
|
|
| 133 |
if not vocal_flag:
|
| 134 |
return None, json.dumps(f"The lyric must contain at least one of the following structures: {vocal_structs}")
|
|
|
|
| 135 |
lyric_norm = " ; ".join(paragraphs_norm)
|
| 136 |
|
| 137 |
-
# format prompt
|
| 138 |
if prompt_audio is not None:
|
| 139 |
genre = None
|
| 140 |
description = None
|
|
@@ -143,14 +123,15 @@ def generate_song(lyric, description=None, prompt_audio=None, genre=None, cfg_co
|
|
| 143 |
if description[-1] != ".":
|
| 144 |
description = description + "."
|
| 145 |
|
| 146 |
-
progress(0.0, "
|
| 147 |
start = time.time()
|
| 148 |
|
| 149 |
-
|
|
|
|
|
|
|
| 150 |
|
| 151 |
end = time.time()
|
| 152 |
|
| 153 |
-
# 创建输入配置的JSON
|
| 154 |
input_config = {
|
| 155 |
"lyric": lyric_norm,
|
| 156 |
"genre": genre,
|
|
@@ -159,16 +140,17 @@ def generate_song(lyric, description=None, prompt_audio=None, genre=None, cfg_co
|
|
| 159 |
"params": params,
|
| 160 |
"inference_duration": end - start,
|
| 161 |
"timestamp": datetime.now().isoformat(),
|
|
|
|
| 162 |
}
|
| 163 |
|
| 164 |
filepath = save_as_flac(sample_rate, audio_data)
|
| 165 |
return filepath, json.dumps(input_config, indent=2)
|
| 166 |
|
| 167 |
|
| 168 |
-
#
|
| 169 |
-
with gr.Blocks(title="
|
| 170 |
-
gr.Markdown("# 🎵
|
| 171 |
-
gr.Markdown("
|
| 172 |
|
| 173 |
with gr.Row():
|
| 174 |
with gr.Column():
|
|
@@ -177,36 +159,21 @@ with gr.Blocks(title="SongGeneration Demo Space") as demo:
|
|
| 177 |
lines=5,
|
| 178 |
max_lines=15,
|
| 179 |
value=EXAMPLE_LYRICS,
|
| 180 |
-
info="
|
| 181 |
-
placeholder="""Lyric Format
|
| 182 |
-
'''
|
| 183 |
-
[structure tag]
|
| 184 |
-
lyrics
|
| 185 |
-
|
| 186 |
-
[structure tag]
|
| 187 |
-
lyrics
|
| 188 |
-
'''
|
| 189 |
-
1. One paragraph represents one segments, starting with a structure tag and ending with a blank line
|
| 190 |
-
2. One line represents one sentence, punctuation is not recommended inside the sentence
|
| 191 |
-
3. The following segments should not contain lyrics: [intro-short], [intro-medium], [inst-short], [inst-medium], [outro-short], [outro-medium]
|
| 192 |
-
4. The following segments require lyrics: [verse], [chorus], [bridge]
|
| 193 |
-
"""
|
| 194 |
)
|
| 195 |
|
| 196 |
with gr.Tabs(elem_id="extra-tabs"):
|
| 197 |
with gr.Tab("Genre Select"):
|
| 198 |
genre = gr.Radio(
|
| 199 |
choices=["Auto", "Pop", "Latin", "Rock", "Electronic", "Metal", "Country", "R&B/Soul", "Ballad", "Jazz", "World", "Hip-Hop", "Funk", "Soundtrack"],
|
| 200 |
-
label="Genre Select(Optional)",
|
| 201 |
value="Auto",
|
| 202 |
-
interactive=True
|
| 203 |
-
elem_id="single-select-radio"
|
| 204 |
)
|
| 205 |
with gr.Tab("Text Prompt"):
|
| 206 |
-
gr.Markdown("For detailed usage, please refer to [here](https://github.com/tencent-ailab/SongGeneration?tab=readme-ov-file#-description-input-format)")
|
| 207 |
description = gr.Textbox(
|
| 208 |
label="Song Description (Optional)",
|
| 209 |
-
info="
|
| 210 |
placeholder="female, rock, motivational, electric guitar, bass guitar, drum kit.",
|
| 211 |
lines=1,
|
| 212 |
max_lines=2
|
|
@@ -214,81 +181,37 @@ lyrics
|
|
| 214 |
with gr.Tab("Audio Prompt"):
|
| 215 |
prompt_audio = gr.Audio(
|
| 216 |
label="Prompt Audio (Optional)",
|
| 217 |
-
type="filepath"
|
| 218 |
-
elem_id="audio-prompt"
|
| 219 |
)
|
| 220 |
|
| 221 |
with gr.Accordion("Advanced Config", open=False):
|
| 222 |
-
cfg_coef = gr.Slider(
|
| 223 |
-
|
| 224 |
-
|
| 225 |
-
maximum=3.0,
|
| 226 |
-
step=0.1,
|
| 227 |
-
value=1.8,
|
| 228 |
-
interactive=True,
|
| 229 |
-
elem_id="cfg-coef",
|
| 230 |
-
)
|
| 231 |
-
temperature = gr.Slider(
|
| 232 |
-
label="Temperature",
|
| 233 |
-
minimum=0.1,
|
| 234 |
-
maximum=2.0,
|
| 235 |
-
step=0.1,
|
| 236 |
-
value=0.8,
|
| 237 |
-
interactive=True,
|
| 238 |
-
elem_id="temperature",
|
| 239 |
-
)
|
| 240 |
-
# top_k = gr.Slider(
|
| 241 |
-
# label="Top-K",
|
| 242 |
-
# minimum=1,
|
| 243 |
-
# maximum=100,
|
| 244 |
-
# step=1,
|
| 245 |
-
# value=50,
|
| 246 |
-
# interactive=True,
|
| 247 |
-
# elem_id="top_k",
|
| 248 |
-
# )
|
| 249 |
with gr.Row():
|
| 250 |
-
generate_btn = gr.Button("Generate Song", variant="primary")
|
| 251 |
-
# generate_bgm_btn = gr.Button("Generate Pure Music", variant="primary")
|
| 252 |
|
| 253 |
with gr.Column():
|
| 254 |
output_audio = gr.Audio(label="Generated Song", type="filepath")
|
| 255 |
output_json = gr.JSON(label="Generated Info")
|
| 256 |
|
| 257 |
-
# # 示例按钮
|
| 258 |
-
# examples = gr.Examples(
|
| 259 |
-
# examples=[
|
| 260 |
-
# ["male, bright, rock, happy, electric guitar and drums, the bpm is 150."],
|
| 261 |
-
# ["female, warm, jazz, romantic, synthesizer and piano, the bpm is 100."]
|
| 262 |
-
# ],
|
| 263 |
-
# inputs=[description],
|
| 264 |
-
# label="Text Prompt examples"
|
| 265 |
-
# )
|
| 266 |
-
|
| 267 |
-
# examples = gr.Examples(
|
| 268 |
-
# examples=[
|
| 269 |
-
# "[intro-medium]\n\n[verse]\n在这个疯狂的世界里\n谁不渴望一点改变\n在爱情面前\n我们都显得那么不安全\n你紧紧抱着我\n告诉我再靠近一点\n别让这璀璨的夜晚白白浪费\n我那迷茫的眼睛\n看不见未来的路\n在情感消散之前\n我们对爱的渴望永不熄灭\n你给我留下一句誓言\n想知道我们的爱是否能持续到永远\n[chorus]\n\n约定在那最后的夜晚\n不管命运如何摆布\n我们的心是否依然如初\n我会穿上红衬衫\n带着摇滚的激情\n回到我们初遇的地方\n约定在那最后的夜晚\n就算全世界都变了样\n我依然坚守诺言\n铭记这一天\n你永远是我心中的爱恋\n\n[outro-medium]\n",
|
| 270 |
-
# "[intro-short]\n\n[verse]\nThrough emerald canyons where fireflies dwell\nCerulean berries kiss morning's first swell\nCrystalline dew crowns each Vitamin Dawn's confection dissolves slowly on me\nAmbrosia breezes through honeycomb vines\nNature's own candy in Fibonacci lines\n[chorus] Blueberry fruit so sweet\n takes you higher\n can't be beat\n In your lungs\n it starts to swell\n You're under its spell\n [verse] Resin of sunlight in candied retreat\nMarmalade moonbeams melt under bare feet\nNectar spirals bloom chloroplast champagne\nPhotosynthesis sings through my veins\nChlorophyll rhythms pulse warm in my blood\nThe forest's green pharmacy floods every bud[chorus] Blueberry fruit so sweet\n takes you higher\n can't be beat\n In your lungs\n it starts to swell\n You're under its spell\n feel the buzz\n ride the wave\n Limey me\n blueberry\n your mind's enslaved\n In the haze\n lose all time\n floating free\n feeling fine\n Blueberry\n fruit so sweet\n takes you higher\n can't be beat\n In your lungs\n it starts to swell\n cry\n You're under its spell\n\n[outro-short]\n",
|
| 271 |
-
# ],
|
| 272 |
-
# inputs=[lyric],
|
| 273 |
-
# label="Lyrics examples",
|
| 274 |
-
# )
|
| 275 |
-
|
| 276 |
-
# 生成按钮点击事件
|
| 277 |
generate_btn.click(
|
| 278 |
fn=generate_song,
|
| 279 |
inputs=[lyric, description, prompt_audio, genre, cfg_coef, temperature, gr.State(5000)],
|
| 280 |
outputs=[output_audio, output_json]
|
| 281 |
)
|
| 282 |
-
# generate_bgm_btn.click(
|
| 283 |
-
# fn=generate_song,
|
| 284 |
-
# inputs=[lyric, description, prompt_audio, genre, cfg_coef, temperature, gr.State(50), gr.State("bgm")],
|
| 285 |
-
# outputs=[output_audio, output_json]
|
| 286 |
-
# )
|
| 287 |
-
|
| 288 |
|
| 289 |
-
#
|
| 290 |
if __name__ == "__main__":
|
| 291 |
torch.set_num_threads(1)
|
| 292 |
-
|
| 293 |
-
|
| 294 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 13 |
|
| 14 |
from download import download_model
|
| 15 |
|
| 16 |
+
# 🎯 خطوة السيادة الأولى: توجيه المحرك لتحميل أوزانكِ الخاصة بدلاً من المستودع العام
|
| 17 |
APP_DIR = op.dirname(op.abspath(__file__))
|
| 18 |
+
MODEL_ID = "Novix/SongGenerationtwo" # مستودع أوزانكِ السيادية
|
|
|
|
| 19 |
|
| 20 |
+
print(f"⏳ [Novix Core] جاري سحب الأوزان السيادية من المستودع: {MODEL_ID}...")
|
| 21 |
+
try:
|
| 22 |
+
# تحميل الأوزان مباشرة إلى البيئة المحلية للـ Space
|
| 23 |
+
download_model(APP_DIR, repo_id=MODEL_ID, revision="main")
|
| 24 |
+
print("✅ تم تحميل الأوزان السيادية لـ Novix بنجاح.")
|
| 25 |
+
except Exception as e:
|
| 26 |
+
print(f"⚠️ تنبيه أثناء تحميل الأوزان: {e}. سيتم الاعتماد على الأوزان المحلية إن وجدت.")
|
| 27 |
+
|
| 28 |
+
# تهيئة وإقلاع المحرك من الفئة الأصلية المستقرة
|
| 29 |
from levo_inference import LeVoInference
|
| 30 |
+
MODEL = None
|
| 31 |
|
| 32 |
EXAMPLE_LYRICS = """
|
| 33 |
[intro-medium]
|
| 34 |
|
| 35 |
[verse]
|
| 36 |
+
随风去流浪
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 37 |
我不想停留原地
|
| 38 |
原地只有无尽循环
|
| 39 |
不再规划人生
|
| 40 |
不再遵循地图
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 41 |
|
| 42 |
[chorus]
|
| 43 |
让我随风去流浪
|
| 44 |
+
邂逅未知的自己
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 45 |
生命最绚烂的章节
|
|
|
|
|
|
|
| 46 |
""".strip()
|
| 47 |
|
| 48 |
+
# قراءة قاموس التوكنز الصوتي الأصلي للموديل
|
| 49 |
+
vocab_path = op.join(APP_DIR, 'conf/vocab.yaml')
|
| 50 |
+
if op.exists(vocab_path):
|
| 51 |
+
with open(vocab_path, 'r', encoding='utf-8') as file:
|
| 52 |
+
STRUCTS = yaml.safe_load(file)
|
| 53 |
+
else:
|
| 54 |
+
STRUCTS = ['[intro]', '[intro-short]', '[intro-medium]', '[verse]', '[chorus]', '[bridge]', '[inst]', '[inst-short]', '[inst-medium]', '[outro]', '[outro-short]', '[outro-medium]']
|
| 55 |
|
| 56 |
def save_as_flac(sample_rate, audio_data):
|
| 57 |
if isinstance(audio_data, tuple):
|
| 58 |
sample_rate, audio_data = audio_data
|
| 59 |
+
|
| 60 |
if audio_data.dtype == np.float64:
|
| 61 |
audio_data = audio_data.astype(np.float32)
|
| 62 |
+
|
| 63 |
temp_file = tempfile.NamedTemporaryFile(delete=False, suffix=".flac")
|
| 64 |
sf.write(temp_file, audio_data, sample_rate, format='FLAC')
|
| 65 |
return temp_file.name
|
| 66 |
|
| 67 |
+
# دالة التوليد الأصلية بعد ربطها بـ Novix Core
|
|
|
|
| 68 |
def generate_song(lyric, description=None, prompt_audio=None, genre=None, cfg_coef=None, temperature=0.1, top_k=-1, gen_type="mixed", progress=gr.Progress(track_tqdm=True)):
|
| 69 |
global MODEL
|
| 70 |
global STRUCTS
|
| 71 |
+
|
| 72 |
+
if MODEL is None:
|
| 73 |
+
return None, json.dumps({"error": "المحرك لم يتم تحميله في الذاكرة بعد. يرجى إعادة تحديث الصفحة أو مراجعة السجلات."})
|
| 74 |
+
|
| 75 |
+
params = {'cfg_coef': cfg_coef, 'temperature': temperature, 'top_k': top_k}
|
| 76 |
+
params = {k: v for k, v in params.items() if v is not None}
|
| 77 |
vocal_structs = ['[verse]', '[chorus]', '[bridge]']
|
| 78 |
sample_rate = MODEL.cfg.sample_rate
|
| 79 |
|
| 80 |
+
# تنسيق وتطهير الكلمات والمقاطع الهيكلية
|
| 81 |
lyric = lyric.replace("[intro]", "[intro-short]").replace("[inst]", "[inst-short]").replace("[outro]", "[outro-short]")
|
| 82 |
paragraphs = [p.strip() for p in lyric.strip().split('\n\n') if p.strip()]
|
| 83 |
+
|
| 84 |
if len(paragraphs) < 1:
|
| 85 |
return None, json.dumps("Lyrics can not be left blank")
|
| 86 |
+
|
| 87 |
paragraphs_norm = []
|
| 88 |
vocal_flag = False
|
| 89 |
+
|
| 90 |
for para in paragraphs:
|
| 91 |
lines = para.splitlines()
|
| 92 |
struct_tag = lines[0].strip().lower()
|
| 93 |
+
|
| 94 |
if struct_tag not in STRUCTS:
|
| 95 |
return None, json.dumps(f"Segments should start with a structure tag in {STRUCTS}")
|
| 96 |
+
|
| 97 |
if struct_tag in vocal_structs:
|
| 98 |
vocal_flag = True
|
| 99 |
if len(lines) < 2 or not [line.strip() for line in lines[1:] if line.strip()]:
|
|
|
|
| 109 |
else:
|
| 110 |
new_para_str = struct_tag
|
| 111 |
paragraphs_norm.append(new_para_str)
|
| 112 |
+
|
| 113 |
if not vocal_flag:
|
| 114 |
return None, json.dumps(f"The lyric must contain at least one of the following structures: {vocal_structs}")
|
| 115 |
+
|
| 116 |
lyric_norm = " ; ".join(paragraphs_norm)
|
| 117 |
|
|
|
|
| 118 |
if prompt_audio is not None:
|
| 119 |
genre = None
|
| 120 |
description = None
|
|
|
|
| 123 |
if description[-1] != ".":
|
| 124 |
description = description + "."
|
| 125 |
|
| 126 |
+
progress(0.0, "⚡ [Novix Core] التوليد مستمر الآن...")
|
| 127 |
start = time.time()
|
| 128 |
|
| 129 |
+
# تشغيل المصفوفات الحقيقية للأوزان المستقلة
|
| 130 |
+
prompt_path = op.join(APP_DIR, "tools/new_prompt.pt")
|
| 131 |
+
audio_data = MODEL(lyric_norm, description, prompt_audio, genre, prompt_path, gen_type, params).cpu().permute(1, 0).float().numpy()
|
| 132 |
|
| 133 |
end = time.time()
|
| 134 |
|
|
|
|
| 135 |
input_config = {
|
| 136 |
"lyric": lyric_norm,
|
| 137 |
"genre": genre,
|
|
|
|
| 140 |
"params": params,
|
| 141 |
"inference_duration": end - start,
|
| 142 |
"timestamp": datetime.now().isoformat(),
|
| 143 |
+
"engine": "Novix Sovereign Studio (Independent Mode)"
|
| 144 |
}
|
| 145 |
|
| 146 |
filepath = save_as_flac(sample_rate, audio_data)
|
| 147 |
return filepath, json.dumps(input_config, indent=2)
|
| 148 |
|
| 149 |
|
| 150 |
+
# بناء الواجهة الاحترافية الكبرى لـ Gradio
|
| 151 |
+
with gr.Blocks(title="Novix Sovereign Studio Pro") as demo:
|
| 152 |
+
gr.Markdown("# 🎵 استوديو Novix المستقل والمملوك لك بالكامل 100%")
|
| 153 |
+
gr.Markdown("🛡️ تم فك الارتباط من خوادم الشركات وتوجيه النواة لأوزانكِ الخاصة للإنتاج والربح الحر.")
|
| 154 |
|
| 155 |
with gr.Row():
|
| 156 |
with gr.Column():
|
|
|
|
| 159 |
lines=5,
|
| 160 |
max_lines=15,
|
| 161 |
value=EXAMPLE_LYRICS,
|
| 162 |
+
info="قوالب المقاطع الصوتية المدعومة: [intro], [verse], [chorus], [bridge], [inst], [outro]"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 163 |
)
|
| 164 |
|
| 165 |
with gr.Tabs(elem_id="extra-tabs"):
|
| 166 |
with gr.Tab("Genre Select"):
|
| 167 |
genre = gr.Radio(
|
| 168 |
choices=["Auto", "Pop", "Latin", "Rock", "Electronic", "Metal", "Country", "R&B/Soul", "Ballad", "Jazz", "World", "Hip-Hop", "Funk", "Soundtrack"],
|
| 169 |
+
label="Genre Select (Optional)",
|
| 170 |
value="Auto",
|
| 171 |
+
interactive=True
|
|
|
|
| 172 |
)
|
| 173 |
with gr.Tab("Text Prompt"):
|
|
|
|
| 174 |
description = gr.Textbox(
|
| 175 |
label="Song Description (Optional)",
|
| 176 |
+
info="اكتبي مواصفات الصوت بالأرقام أو الإنجليزية (مثال: female, sad pop, piano).",
|
| 177 |
placeholder="female, rock, motivational, electric guitar, bass guitar, drum kit.",
|
| 178 |
lines=1,
|
| 179 |
max_lines=2
|
|
|
|
| 181 |
with gr.Tab("Audio Prompt"):
|
| 182 |
prompt_audio = gr.Audio(
|
| 183 |
label="Prompt Audio (Optional)",
|
| 184 |
+
type="filepath"
|
|
|
|
| 185 |
)
|
| 186 |
|
| 187 |
with gr.Accordion("Advanced Config", open=False):
|
| 188 |
+
cfg_coef = gr.Slider(label="CFG Coefficient", minimum=0.1, maximum=3.0, step=0.1, value=1.8, interactive=True)
|
| 189 |
+
temperature = gr.Slider(label="Temperature", minimum=0.1, maximum=2.0, step=0.1, value=0.8, interactive=True)
|
| 190 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 191 |
with gr.Row():
|
| 192 |
+
generate_btn = gr.Button("Generate Song (Sovereign Mode)", variant="primary")
|
|
|
|
| 193 |
|
| 194 |
with gr.Column():
|
| 195 |
output_audio = gr.Audio(label="Generated Song", type="filepath")
|
| 196 |
output_json = gr.JSON(label="Generated Info")
|
| 197 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 198 |
generate_btn.click(
|
| 199 |
fn=generate_song,
|
| 200 |
inputs=[lyric, description, prompt_audio, genre, cfg_coef, temperature, gr.State(5000)],
|
| 201 |
outputs=[output_audio, output_json]
|
| 202 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 203 |
|
| 204 |
+
# تشغيل الإقلاع المستقل للنواة
|
| 205 |
if __name__ == "__main__":
|
| 206 |
torch.set_num_threads(1)
|
| 207 |
+
ckpt_path = op.join(APP_DIR, "ckpt")
|
| 208 |
+
|
| 209 |
+
# التأكد من وجود مجلد الأوزان وإقلاع النموذج فوراً
|
| 210 |
+
if not op.exists(ckpt_path):
|
| 211 |
+
os.makedirs(ckpt_path, exist_ok=True)
|
| 212 |
+
|
| 213 |
+
print("🧠 جاري صهر وبناء بيئة الاستدلال الصوتي المستقل...")
|
| 214 |
+
MODEL = LeVoInference(ckpt_path)
|
| 215 |
+
print("✅ النصر الكلي! الاستوديو شغال أوفلاين وجاهز لاستقبال ضربة زر التوليد.")
|
| 216 |
+
|
| 217 |
+
demo.launch(server_name="0.0.0.0", server_port=7860)
|