perf: slim daw_engine bundle 409MB->170MB + fix engine khong chay tren Windows
- Thay librosa bang app/core/audio_features.py (numpy/scipy/soundfile):
load, beat_track, frames_to_time, spectral_centroid, rms, zero_crossing_rate,
time_stretch, pitch_shift, chroma_stft. A/B ngang librosa (BPM <1% sai lech,
pitch_shift chuan toi Hz). Loai bo llvmlite 171MB + scikit-learn + numba.
- Task layer 2 che do (app/tasks/worker.py): server giu celery; desktop slim
chay in-process thread + registry, giu nguyen API contract (.delay/.id/status
/tasks/{id}) nen frontend khong doi.
- engine.spec: excludes librosa/numba/llvmlite/sklearn/celery/redis/kombu/
billiard/amqp/msgpack/yaml/PIL/cairosvg/zstandard/...; scan scipy gioi han
scipy.signal; giu click (uvicorn.main import click).
- render_engine: scipy.signal thanh lazy import (giam cold start).
- tauri.conf.json: targets [nsis, msi] - NSIS tro lai (bundle nho) de
hooks.nsh cai VC++ Redistributable - sua bug daw_engine.exe khong chay
tren Windows (truoc day MSI-only khong chay hooks).
- build_linux.sh / build_macos.sh: build 1 lenh moi OS.
- Doc: DESKTOP_INSTALL_PLAN.md muc 5.1.
- Verify: 86 tests pass, engine dong goi upload/analyze/waveform/export OK.
This commit is contained in:
+21
-12
@@ -1,19 +1,28 @@
|
||||
import os
|
||||
import json
|
||||
import librosa
|
||||
import numpy as np
|
||||
from typing import Optional
|
||||
|
||||
# Thay librosa bang shim nhe (numpy/scipy/soundfile) — khong keo numba/llvmlite
|
||||
from app.core.audio_features import (
|
||||
load as _load,
|
||||
beat_track as _beat_track,
|
||||
frames_to_time as _frames_to_time,
|
||||
spectral_centroid as _spectral_centroid,
|
||||
rms as _rms,
|
||||
zero_crossing_rate as _zcr,
|
||||
)
|
||||
|
||||
|
||||
def analyze_audio(file_path: str) -> dict:
|
||||
"""
|
||||
Phân tích âm thanh: BPM, beat tracking, ước lượng bars.
|
||||
"""
|
||||
# Load audio
|
||||
y, sr = librosa.load(file_path, sr=None)
|
||||
y, sr = _load(file_path, sr=None)
|
||||
|
||||
# Track beats
|
||||
tempo, beat_frames = librosa.beat.beat_track(y=y, sr=sr)
|
||||
tempo, beat_frames = _beat_track(y=y, sr=sr)
|
||||
|
||||
# Handle tempo which might be scalar or numpy array in different librosa versions
|
||||
if isinstance(tempo, np.ndarray):
|
||||
@@ -25,7 +34,7 @@ def analyze_audio(file_path: str) -> dict:
|
||||
bpm = float(tempo)
|
||||
|
||||
# Convert frames to time (seconds)
|
||||
beat_times = librosa.frames_to_time(beat_frames, sr=sr).tolist()
|
||||
beat_times = _frames_to_time(beat_frames, sr=sr).tolist()
|
||||
|
||||
# Estimate bars (assume 4/4 time signature - grouping every 4 beats)
|
||||
bar_times = [beat_times[i] for i in range(0, len(beat_times), 4)]
|
||||
@@ -43,31 +52,31 @@ def analyze_audio_advanced(file_path: str) -> dict:
|
||||
Phân tích âm thanh nâng cao: BPM, beats, bars, spectral features.
|
||||
Sử dụng librosa để trích xuất đặc trưng âm học chi tiết.
|
||||
"""
|
||||
y, sr = librosa.load(file_path, sr=None)
|
||||
y, sr = _load(file_path, sr=None)
|
||||
duration = float(len(y)) / sr
|
||||
|
||||
# Beat tracking
|
||||
tempo, beat_frames = librosa.beat.beat_track(y=y, sr=sr)
|
||||
tempo, beat_frames = _beat_track(y=y, sr=sr)
|
||||
|
||||
if isinstance(tempo, np.ndarray):
|
||||
bpm = float(tempo[0]) if tempo.size > 0 else 120.0
|
||||
else:
|
||||
bpm = float(tempo)
|
||||
|
||||
beat_times = librosa.frames_to_time(beat_frames, sr=sr).tolist()
|
||||
beat_times = _frames_to_time(beat_frames, sr=sr).tolist()
|
||||
bar_times = [beat_times[i] for i in range(0, len(beat_times), 4)]
|
||||
|
||||
# Spectral centroid (brightness)
|
||||
spectral_centroids = librosa.feature.spectral_centroid(y=y, sr=sr)[0]
|
||||
spectral_centroids = _spectral_centroid(y=y, sr=sr)[0]
|
||||
avg_brightness = float(np.mean(spectral_centroids))
|
||||
|
||||
# RMS energy
|
||||
rms = librosa.feature.rms(y=y)[0]
|
||||
avg_energy = float(np.mean(rms))
|
||||
rms_vals = _rms(y=y)[0]
|
||||
avg_energy = float(np.mean(rms_vals))
|
||||
|
||||
# Zero crossing rate
|
||||
zcr = librosa.feature.zero_crossing_rate(y)[0]
|
||||
avg_zcr = float(np.mean(zcr))
|
||||
zcr_vals = _zcr(y)[0]
|
||||
avg_zcr = float(np.mean(zcr_vals))
|
||||
|
||||
return {
|
||||
"bpm": round(bpm, 2),
|
||||
|
||||
Reference in New Issue
Block a user