Skip to content

Commit f8a819d

Browse files
authored
fix: 修复牛牛唱歌失效问题
记得更新依赖
1 parent 3c0c98e commit f8a819d

File tree

7 files changed

+110
-45
lines changed

7 files changed

+110
-45
lines changed

app/api/endpoints/sing.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ async def sing_endpoint(request_id: str, request: SingRequest):
1212
return SingResponse(task_id=task_id, status="processing")
1313

1414

15-
@router.get("/play/{request_id}", response_model=SingResponse)
16-
async def play_endpoint(request_id: str, speaker: str = ""):
17-
await play(request_id, speaker)
18-
return SingResponse(task_id="", status="processing")
15+
@router.get("/play/{speaker}", response_model=SingResponse)
16+
async def play_endpoint(speaker: str):
17+
task_id = await play(speaker)
18+
return SingResponse(task_id=task_id, status="processing")

app/services/callback.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,3 +31,17 @@ async def callback_audio(request_id: str, audio: bytes):
3131
{"status": "success"},
3232
files={"file": audio},
3333
)
34+
35+
36+
async def callback_audio_with_info(request_id: str, audio: bytes, song_id: str, chunk_index: int, key: int):
37+
callback_url = f"{CALLBACK_URL}/{request_id}"
38+
await send_callback(
39+
callback_url,
40+
{
41+
"status": "success",
42+
"song_id": song_id,
43+
"chunk_index": chunk_index,
44+
"key": key,
45+
},
46+
files={"file": audio},
47+
)

app/services/sing.py

Lines changed: 6 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,8 @@
1-
import random
2-
from pathlib import Path
1+
from ulid import ULID
32

43
from app.core.config import settings
54
from app.core.logger import logger
6-
from app.services.callback import callback_audio, callback_failed
7-
from app.tasks.sing import sing_task
8-
9-
SONG_PATH = "resource/sing/splices/"
10-
MUSIC_PATH = "resource/music/"
5+
from app.tasks.sing import play_task, sing_task
116

127

138
async def sing(request_id: str, speaker: str, song_id: int, key: int, chunk_index: int):
@@ -16,38 +11,8 @@ async def sing(request_id: str, speaker: str, song_id: int, key: int, chunk_inde
1611
return task.id
1712

1813

19-
def get_random_song(speaker: str = ""):
20-
all_song = []
21-
if Path(SONG_PATH).exists():
22-
all_song = [
23-
str(s)
24-
for s in Path(SONG_PATH).iterdir()
25-
# 只唱过一段的大概率不是什么好听的,排除下
26-
if speaker in s.name and "_spliced0" not in s.name
27-
]
28-
if not all_song:
29-
all_song = [MUSIC_PATH + s for s in Path(MUSIC_PATH).iterdir()]
30-
31-
if not all_song:
32-
return None
33-
return random.choice(all_song)
34-
35-
3614
async def play(speaker: str = ""):
37-
rand_music = get_random_song(speaker)
38-
if not rand_music:
39-
await callback_failed()
40-
return
41-
42-
if "_spliced" in rand_music:
43-
splited = Path(rand_music).stem.split("_")
44-
song_id = splited[0]
45-
chunk_index = int(splited[1].replace("spliced", "")) + 1
46-
elif "_full_" in rand_music:
47-
song_id = Path(rand_music).stem.split("_")[0]
48-
chunk_index = 114514
49-
else:
50-
song_id = ""
51-
chunk_index = 114514
52-
53-
await callback_audio(speaker, song_id, 0, chunk_index, rand_music)
15+
request_id = str(ULID())
16+
task = play_task.delay(request_id, speaker)
17+
logger.info(f"Task {task.id} started")
18+
return request_id

app/tasks/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
from app.tasks.chat.chat_tasks import chat_task
2+
from app.tasks.sing.play_tasks import play_task
23
from app.tasks.sing.sing_tasks import sing_task

app/tasks/sing/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1+
from app.tasks.sing.play_tasks import play_task
12
from app.tasks.sing.sing_tasks import sing_task

app/tasks/sing/play_tasks.py

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
import asyncio
2+
import random
3+
from pathlib import Path
4+
5+
import anyio
6+
7+
from app.core.celery import celery_app
8+
from app.services.callback import callback_audio_with_info, callback_failed
9+
10+
SONG_PATH = "resource/sing/splices/"
11+
MUSIC_PATH = "resource/music/"
12+
13+
14+
def get_random_song(speaker: str = ""):
15+
all_song = []
16+
song_dir = Path(SONG_PATH)
17+
if song_dir.exists():
18+
all_song = [str(s) for s in song_dir.iterdir() if speaker in s.name and "_spliced0" not in s.name]
19+
20+
if not all_song:
21+
music_dir = Path(MUSIC_PATH)
22+
if music_dir.exists():
23+
all_song = [str(s) for s in music_dir.iterdir()]
24+
25+
if not all_song:
26+
return None
27+
return random.choice(all_song)
28+
29+
30+
@celery_app.task(name="play")
31+
def play_task(request_id: str, speaker: str = ""):
32+
loop = asyncio.new_event_loop()
33+
asyncio.set_event_loop(loop)
34+
try:
35+
return loop.run_until_complete(_play_task_async(request_id, speaker))
36+
finally:
37+
loop.close()
38+
39+
40+
async def _play_task_async(request_id: str, speaker: str = ""):
41+
try:
42+
rand_music = get_random_song(speaker)
43+
if not rand_music:
44+
await callback_failed(request_id)
45+
return False
46+
47+
if "_spliced" in rand_music:
48+
splited = Path(rand_music).stem.split("_")
49+
song_id = splited[0]
50+
chunk_index = int(splited[1].replace("spliced", "")) + 1
51+
if "key" in rand_music:
52+
key_index = next((i for i, part in enumerate(splited) if "key" in part), None)
53+
if key_index is not None:
54+
try:
55+
key = int(splited[key_index].replace("key", ""))
56+
except ValueError:
57+
key = 0
58+
else:
59+
key = 0
60+
else:
61+
key = 0
62+
elif "_full_" in rand_music:
63+
song_id = Path(rand_music).stem.split("_")[0]
64+
chunk_index = 114514
65+
key = 0
66+
else:
67+
song_id = ""
68+
chunk_index = 114514
69+
key = 0
70+
71+
try:
72+
async with await anyio.open_file(rand_music, "rb") as f:
73+
audio_content = await f.read()
74+
except Exception:
75+
await callback_failed(request_id)
76+
return False
77+
78+
await callback_audio_with_info(request_id, audio_content, song_id=song_id, chunk_index=chunk_index, key=key)
79+
return True
80+
except Exception:
81+
await callback_failed(request_id)
82+
return False

pyproject.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ sing = [
4949
"torchfcpe>=0.0.4",
5050
"tqdm>=4.66.5",
5151
"transformers>=4.49.0",
52+
"python-ulid>=3.0.0",
5253
]
5354
tts = [
5455
"numpy==1.26.4",
@@ -70,6 +71,7 @@ tts = [
7071
"cn2an>=0.5.23",
7172
"pyopenjtalk>=0.4.1",
7273
"opencc>=1.1.9",
74+
"tensorboardx==2.6.4",
7375
]
7476

7577
[tool.uv]

0 commit comments

Comments
 (0)