Spaces:
Sleeping
Sleeping
Commit
·
2916663
1
Parent(s):
be40b87
add url audio
Browse files- app/api/transcribe.py +49 -39
- app/schemas/transcribe.py +1 -0
app/api/transcribe.py
CHANGED
|
@@ -71,7 +71,7 @@ def _enqueue_async_job(audio_url: str, note_id: str, user_id: str | None = None)
|
|
| 71 |
|
| 72 |
|
| 73 |
|
| 74 |
-
async def _run_sync_pipeline(tmp_wav: str, note_id: str):
|
| 75 |
"""
|
| 76 |
Sync ASR → update existing note
|
| 77 |
"""
|
|
@@ -106,48 +106,54 @@ async def _run_sync_pipeline(tmp_wav: str, note_id: str):
|
|
| 106 |
|
| 107 |
# 🔥 UPDATE — KHÔNG CREATE
|
| 108 |
# Use internal update endpoint to match create_audio_note (internal API)
|
| 109 |
-
|
| 110 |
-
|
| 111 |
-
|
| 112 |
-
|
| 113 |
-
"
|
| 114 |
-
|
| 115 |
-
"
|
| 116 |
-
|
| 117 |
-
|
| 118 |
-
|
| 119 |
-
"asr_model": "PhoWhisper-base",
|
| 120 |
-
}
|
| 121 |
-
},
|
| 122 |
-
"generate": ["normalize", "keywords", "summary", "mindmap"],
|
| 123 |
},
|
| 124 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 125 |
|
| 126 |
return {
|
| 127 |
"note_id": note_id,
|
| 128 |
"status": status,
|
| 129 |
"duration": info.get("duration"),
|
|
|
|
| 130 |
}
|
| 131 |
|
| 132 |
|
| 133 |
-
async def _create_placeholder_note(note_id: str, duration: float):
|
| 134 |
client = NoteServiceClient()
|
| 135 |
-
|
| 136 |
-
|
| 137 |
-
|
| 138 |
-
|
| 139 |
-
|
| 140 |
-
|
| 141 |
-
"
|
| 142 |
-
"
|
| 143 |
-
|
| 144 |
-
|
| 145 |
-
|
| 146 |
-
|
| 147 |
-
|
| 148 |
-
|
| 149 |
-
|
| 150 |
-
|
|
|
|
|
|
|
|
|
|
| 151 |
|
| 152 |
if res is None:
|
| 153 |
# 🔥 FAIL FAST
|
|
@@ -183,7 +189,7 @@ async def transcribe(file: UploadFile = File(...)):
|
|
| 183 |
if duration > ASYNC_THRESHOLD:
|
| 184 |
audio_url = await asyncio.to_thread(upload_temp_audio, tmp_wav)
|
| 185 |
|
| 186 |
-
await _create_placeholder_note(note_id, duration)
|
| 187 |
job = _enqueue_async_job(audio_url, note_id)
|
| 188 |
|
| 189 |
REQUEST_COUNT.labels(endpoint, "queued").inc()
|
|
@@ -194,12 +200,15 @@ async def transcribe(file: UploadFile = File(...)):
|
|
| 194 |
"job_id": job.id,
|
| 195 |
"status": "queued",
|
| 196 |
"duration": duration,
|
|
|
|
| 197 |
},
|
| 198 |
)
|
| 199 |
|
| 200 |
# ---------- SYNC ----------
|
| 201 |
-
|
| 202 |
-
|
|
|
|
|
|
|
| 203 |
|
| 204 |
REQUEST_COUNT.labels(endpoint, "success").inc()
|
| 205 |
return result
|
|
@@ -242,7 +251,7 @@ async def transcribe_url(payload: dict):
|
|
| 242 |
|
| 243 |
# ---------- ASYNC ----------
|
| 244 |
if duration > ASYNC_THRESHOLD:
|
| 245 |
-
await _create_placeholder_note(note_id, duration)
|
| 246 |
job = _enqueue_async_job(audio_url, note_id, user_id)
|
| 247 |
|
| 248 |
REQUEST_COUNT.labels(endpoint, "queued").inc()
|
|
@@ -253,12 +262,13 @@ async def transcribe_url(payload: dict):
|
|
| 253 |
"job_id": job.id,
|
| 254 |
"status": "queued",
|
| 255 |
"duration": duration,
|
|
|
|
| 256 |
},
|
| 257 |
)
|
| 258 |
|
| 259 |
# ---------- SYNC ----------
|
| 260 |
-
await _create_placeholder_note(note_id, duration)
|
| 261 |
-
result = await _run_sync_pipeline(tmp_wav, note_id)
|
| 262 |
|
| 263 |
REQUEST_COUNT.labels(endpoint, "success").inc()
|
| 264 |
return result
|
|
|
|
| 71 |
|
| 72 |
|
| 73 |
|
| 74 |
+
async def _run_sync_pipeline(tmp_wav: str, note_id: str, audio_url: str | None = None):
|
| 75 |
"""
|
| 76 |
Sync ASR → update existing note
|
| 77 |
"""
|
|
|
|
| 106 |
|
| 107 |
# 🔥 UPDATE — KHÔNG CREATE
|
| 108 |
# Use internal update endpoint to match create_audio_note (internal API)
|
| 109 |
+
payload = {
|
| 110 |
+
"status": status,
|
| 111 |
+
"raw_text": text,
|
| 112 |
+
"metadata": {
|
| 113 |
+
"audio": {
|
| 114 |
+
"duration": info.get("duration"),
|
| 115 |
+
"sample_rate": info.get("samplerate"),
|
| 116 |
+
"chunks": chunks,
|
| 117 |
+
"asr_model": "PhoWhisper-base",
|
| 118 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
| 119 |
},
|
| 120 |
+
"generate": ["normalize", "keywords", "summary", "mindmap"],
|
| 121 |
+
}
|
| 122 |
+
|
| 123 |
+
if audio_url:
|
| 124 |
+
payload["metadata"]["audio"]["url"] = audio_url
|
| 125 |
+
|
| 126 |
+
await note_service.update_note_internal(note_id, payload)
|
| 127 |
|
| 128 |
return {
|
| 129 |
"note_id": note_id,
|
| 130 |
"status": status,
|
| 131 |
"duration": info.get("duration"),
|
| 132 |
+
"audio_url": audio_url,
|
| 133 |
}
|
| 134 |
|
| 135 |
|
| 136 |
+
async def _create_placeholder_note(note_id: str, duration: float, audio_url: str | None = None):
|
| 137 |
client = NoteServiceClient()
|
| 138 |
+
payload = {
|
| 139 |
+
"note_id": note_id,
|
| 140 |
+
"type": "audio",
|
| 141 |
+
"status": "processing",
|
| 142 |
+
"raw_text": "",
|
| 143 |
+
"metadata": {
|
| 144 |
+
"audio": {
|
| 145 |
+
"duration": duration,
|
| 146 |
+
"chunks": [],
|
| 147 |
+
"asr_model": "PhoWhisper-base",
|
| 148 |
+
}
|
| 149 |
+
},
|
| 150 |
+
# ❌ KHÔNG generate ở đây
|
| 151 |
+
}
|
| 152 |
+
|
| 153 |
+
if audio_url:
|
| 154 |
+
payload["metadata"]["audio"]["url"] = audio_url
|
| 155 |
+
|
| 156 |
+
res = await client.create_audio_note(payload)
|
| 157 |
|
| 158 |
if res is None:
|
| 159 |
# 🔥 FAIL FAST
|
|
|
|
| 189 |
if duration > ASYNC_THRESHOLD:
|
| 190 |
audio_url = await asyncio.to_thread(upload_temp_audio, tmp_wav)
|
| 191 |
|
| 192 |
+
await _create_placeholder_note(note_id, duration, audio_url)
|
| 193 |
job = _enqueue_async_job(audio_url, note_id)
|
| 194 |
|
| 195 |
REQUEST_COUNT.labels(endpoint, "queued").inc()
|
|
|
|
| 200 |
"job_id": job.id,
|
| 201 |
"status": "queued",
|
| 202 |
"duration": duration,
|
| 203 |
+
"audio_url": audio_url,
|
| 204 |
},
|
| 205 |
)
|
| 206 |
|
| 207 |
# ---------- SYNC ----------
|
| 208 |
+
# Upload small audio so we can return a stable URL and persist it
|
| 209 |
+
audio_url = await asyncio.to_thread(upload_temp_audio, tmp_wav)
|
| 210 |
+
await _create_placeholder_note(note_id, duration, audio_url)
|
| 211 |
+
result = await _run_sync_pipeline(tmp_wav, note_id, audio_url)
|
| 212 |
|
| 213 |
REQUEST_COUNT.labels(endpoint, "success").inc()
|
| 214 |
return result
|
|
|
|
| 251 |
|
| 252 |
# ---------- ASYNC ----------
|
| 253 |
if duration > ASYNC_THRESHOLD:
|
| 254 |
+
await _create_placeholder_note(note_id, duration, audio_url)
|
| 255 |
job = _enqueue_async_job(audio_url, note_id, user_id)
|
| 256 |
|
| 257 |
REQUEST_COUNT.labels(endpoint, "queued").inc()
|
|
|
|
| 262 |
"job_id": job.id,
|
| 263 |
"status": "queued",
|
| 264 |
"duration": duration,
|
| 265 |
+
"audio_url": audio_url,
|
| 266 |
},
|
| 267 |
)
|
| 268 |
|
| 269 |
# ---------- SYNC ----------
|
| 270 |
+
await _create_placeholder_note(note_id, duration, audio_url)
|
| 271 |
+
result = await _run_sync_pipeline(tmp_wav, note_id, audio_url)
|
| 272 |
|
| 273 |
REQUEST_COUNT.labels(endpoint, "success").inc()
|
| 274 |
return result
|
app/schemas/transcribe.py
CHANGED
|
@@ -5,3 +5,4 @@ class TranscribeResponse(BaseModel):
|
|
| 5 |
note_id: str
|
| 6 |
status: str
|
| 7 |
duration: Optional[float] = None
|
|
|
|
|
|
| 5 |
note_id: str
|
| 6 |
status: str
|
| 7 |
duration: Optional[float] = None
|
| 8 |
+
audio_url: Optional[str] = None
|