FEAT: thêm nút bypass cho track strip để bypass không qua mastering panel

This commit is contained in:
2026-08-03 15:47:10 +07:00
parent 6f55d36085
commit a9da813cb1
28 changed files with 2076 additions and 233 deletions
+21 -4
View File
@@ -9,7 +9,7 @@ from app.core.render_engine import PythonRenderEngine
from app.core.soundfont_inspector import SoundFontInspector
from app.core.soundfont_converter import SoundFontConverter
from app.core.soundfont_scanner import SoundFontAutoScanner
from app.api.v1.auth import get_current_user
from app.api.v1.auth import get_current_user, enforce_password_changed
router = APIRouter()
@@ -79,11 +79,23 @@ async def upload_soundfont(
background_tasks: BackgroundTasks = None,
current_user: dict = Depends(get_current_user)
):
enforce_password_changed(current_user)
if not (file.filename and (file.filename.endswith(".sf2") or file.filename.endswith(".sf3"))):
raise HTTPException(status_code=400, detail="Only .sf2 / .sf3 files are allowed")
contents = await file.read()
if not PluginManager.validate_sf2_header(contents):
# Stream upload in chunks with a hard size cap (SGM-class fonts can exceed
# 500MB; reading the whole body into RAM would OOM the server).
MAX_SF_UPLOAD_BYTES = 2 * 1024 * 1024 * 1024 # 2 GB
contents = bytearray()
while True:
chunk = await file.read(1024 * 1024)
if not chunk:
break
contents.extend(chunk)
if len(contents) > MAX_SF_UPLOAD_BYTES:
raise HTTPException(status_code=413, detail="SoundFont quá lớn (giới hạn 2GB)")
if not PluginManager.validate_sf2_header(bytes(contents[:4096])):
raise HTTPException(status_code=400, detail="Invalid SoundFont file: missing RIFF/sfbk header")
file_ext = os.path.splitext(file.filename)[1]
@@ -178,8 +190,13 @@ async def render_project(
req: RenderRequest,
current_user: dict = Depends(get_current_user)
):
enforce_password_changed(current_user)
engine = PythonRenderEngine()
output_path = os.path.join(settings.PROCESSED_DIR, req.output_filename or "render_output.wav")
# Prevent path traversal: strip any directory components and force .wav.
safe_name = os.path.basename((req.output_filename or "render_output.wav").replace("\\", "/"))
if not safe_name.lower().endswith(".wav"):
safe_name += ".wav"
output_path = os.path.join(settings.PROCESSED_DIR, safe_name)
try:
result_path = engine.render_project(req.project_json, output_path)
return {"url": f"/static/audio/processed/{os.path.basename(result_path)}", "path": result_path}