Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions app/api/endpoints/sing.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ async def sing_endpoint(request_id: str, request: SingRequest):
return SingResponse(task_id=task_id, status="processing")


@router.get("/play/{request_id}", response_model=SingResponse)
async def play_endpoint(request_id: str, speaker: str = ""):
await play(request_id, speaker)
return SingResponse(task_id="", status="processing")
@router.get("/play/{speaker}", response_model=SingResponse)
async def play_endpoint(speaker: str):
task_id = await play(speaker)
return SingResponse(task_id=task_id, status="processing")
14 changes: 14 additions & 0 deletions app/services/callback.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,17 @@ async def callback_audio(request_id: str, audio: bytes):
{"status": "success"},
files={"file": audio},
)


async def callback_audio_with_info(request_id: str, audio: bytes, song_id: str, chunk_index: int, key: int):
callback_url = f"{CALLBACK_URL}/{request_id}"
await send_callback(
callback_url,
{
"status": "success",
"song_id": song_id,
"chunk_index": chunk_index,
"key": key,
},
files={"file": audio},
)
47 changes: 6 additions & 41 deletions app/services/sing.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,8 @@
import random
from pathlib import Path
from ulid import ULID

from app.core.config import settings
from app.core.logger import logger
from app.services.callback import callback_audio, callback_failed
from app.tasks.sing import sing_task

SONG_PATH = "resource/sing/splices/"
MUSIC_PATH = "resource/music/"
from app.tasks.sing import play_task, sing_task


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


def get_random_song(speaker: str = ""):
all_song = []
if Path(SONG_PATH).exists():
all_song = [
str(s)
for s in Path(SONG_PATH).iterdir()
# 只唱过一段的大概率不是什么好听的,排除下
if speaker in s.name and "_spliced0" not in s.name
]
if not all_song:
all_song = [MUSIC_PATH + s for s in Path(MUSIC_PATH).iterdir()]

if not all_song:
return None
return random.choice(all_song)


async def play(speaker: str = ""):
rand_music = get_random_song(speaker)
if not rand_music:
await callback_failed()
return

if "_spliced" in rand_music:
splited = Path(rand_music).stem.split("_")
song_id = splited[0]
chunk_index = int(splited[1].replace("spliced", "")) + 1
elif "_full_" in rand_music:
song_id = Path(rand_music).stem.split("_")[0]
chunk_index = 114514
else:
song_id = ""
chunk_index = 114514

await callback_audio(speaker, song_id, 0, chunk_index, rand_music)
request_id = str(ULID())
task = play_task.delay(request_id, speaker)
logger.info(f"Task {task.id} started")
return request_id
1 change: 1 addition & 0 deletions app/tasks/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
from app.tasks.chat.chat_tasks import chat_task
from app.tasks.sing.play_tasks import play_task
from app.tasks.sing.sing_tasks import sing_task
1 change: 1 addition & 0 deletions app/tasks/sing/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
from app.tasks.sing.play_tasks import play_task
from app.tasks.sing.sing_tasks import sing_task
82 changes: 82 additions & 0 deletions app/tasks/sing/play_tasks.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import asyncio
import random
from pathlib import Path

import anyio

from app.core.celery import celery_app
from app.services.callback import callback_audio_with_info, callback_failed

SONG_PATH = "resource/sing/splices/"
MUSIC_PATH = "resource/music/"


def get_random_song(speaker: str = ""):
all_song = []
song_dir = Path(SONG_PATH)
if song_dir.exists():
all_song = [str(s) for s in song_dir.iterdir() if speaker in s.name and "_spliced0" not in s.name]

if not all_song:
music_dir = Path(MUSIC_PATH)
if music_dir.exists():
all_song = [str(s) for s in music_dir.iterdir()]

if not all_song:
return None
return random.choice(all_song)


@celery_app.task(name="play")
def play_task(request_id: str, speaker: str = ""):
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
try:
return loop.run_until_complete(_play_task_async(request_id, speaker))
finally:
loop.close()


async def _play_task_async(request_id: str, speaker: str = ""):
try:
rand_music = get_random_song(speaker)
if not rand_music:
await callback_failed(request_id)
return False

if "_spliced" in rand_music:
splited = Path(rand_music).stem.split("_")
song_id = splited[0]
chunk_index = int(splited[1].replace("spliced", "")) + 1
if "key" in rand_music:
key_index = next((i for i, part in enumerate(splited) if "key" in part), None)
if key_index is not None:
try:
key = int(splited[key_index].replace("key", ""))
except ValueError:
key = 0
else:
key = 0
else:
key = 0
elif "_full_" in rand_music:
song_id = Path(rand_music).stem.split("_")[0]
chunk_index = 114514
key = 0
else:
song_id = ""
chunk_index = 114514
key = 0

try:
async with await anyio.open_file(rand_music, "rb") as f:
audio_content = await f.read()
except Exception:
await callback_failed(request_id)
return False

await callback_audio_with_info(request_id, audio_content, song_id=song_id, chunk_index=chunk_index, key=key)
return True
except Exception:
await callback_failed(request_id)
return False
2 changes: 2 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ sing = [
"torchfcpe>=0.0.4",
"tqdm>=4.66.5",
"transformers>=4.49.0",
"python-ulid>=3.0.0",
]
tts = [
"numpy==1.26.4",
Expand All @@ -70,6 +71,7 @@ tts = [
"cn2an>=0.5.23",
"pyopenjtalk>=0.4.1",
"opencc>=1.1.9",
"tensorboardx==2.6.4",
]

[tool.uv]
Expand Down
Loading