feat(sync): 长语音音频本地化(voice_clip media_hash+download+local-first playback)
Mirror download_call_recordings pattern for voice_clips:
- VoiceClip.media_hash column + Alembic migration (c4d5e6f7a8b9)
- VoiceClipOut.media_hash + frontend VoiceClip.media_hash type
- download_voice_clip_audio in app/scraper/media.py (resilient, sha256-dedup,
same download_url/upsert_media helpers as call recordings)
- sync_voice_clip_audio orchestrator wrapper (commits own SyncRun, mirrors
sync_call_recordings semantics)
- scheduler: _run_voice_clip_audio + ENTITY_FUNCS['voice_clip_audio'] +
appended to daily _run_all job (after voice_clips)
- VoiceClipModal playClip local-first: /api/media/{media_hash} with OSS
oss_file_name fallback (mirrors CallList.playRecord)
Tested: 376 pytest pass; vue-tsc clean; migration applied; 1523/1533 clips
localized (10 pending are genuine upstream HTTP 404s — resilient skip).
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -59,6 +59,7 @@ from app.sync.orchestrator import (
|
||||
sync_departments,
|
||||
sync_phone_calls,
|
||||
sync_sms,
|
||||
sync_voice_clip_audio,
|
||||
sync_voice_clips,
|
||||
sync_wa_voice_calls,
|
||||
sync_wechat_accounts,
|
||||
@@ -203,6 +204,13 @@ async def _run_call_recordings(
|
||||
return [await sync_call_recordings(session, client, store)]
|
||||
|
||||
|
||||
async def _run_voice_clip_audio(
|
||||
session: AsyncSession, client: YunkeClient, store: ObjectStore
|
||||
) -> list[SyncResult]:
|
||||
"""Audio-localization pass for already-mirrored ``voice_clip`` rows."""
|
||||
return [await sync_voice_clip_audio(session, client, store)]
|
||||
|
||||
|
||||
async def _run_messages(
|
||||
session: AsyncSession, client: YunkeClient, store: ObjectStore
|
||||
) -> list[SyncResult]:
|
||||
@@ -276,6 +284,12 @@ async def _run_all(
|
||||
# tables. Must run AFTER wechat_accounts + wa_accounts (which seed the
|
||||
# user_id -> channel mapping the voice-clip sync reads).
|
||||
results.append(await sync_voice_clips(session, client))
|
||||
# Voice-clip audio localization: download OSS audio for already-mirrored
|
||||
# voice_clip rows. Runs AFTER voice_clips so freshly-scraped rows are
|
||||
# eligible. Commits internally (mirrors call_recordings) — placing it last
|
||||
# in the daily job means no later in-batch entity can be affected by the
|
||||
# mid-batch commit boundary.
|
||||
results.append(await sync_voice_clip_audio(session, client, store))
|
||||
return results
|
||||
|
||||
|
||||
@@ -297,6 +311,7 @@ ENTITY_FUNCS: dict[
|
||||
"sms": _run_sms,
|
||||
"voice_clips": _run_voice_clips,
|
||||
"call_recordings": _run_call_recordings,
|
||||
"voice_clip_audio": _run_voice_clip_audio,
|
||||
"messages": _run_messages,
|
||||
"wa_messages": _run_wa_messages,
|
||||
"all_wechat": _run_all_wechat,
|
||||
|
||||
Reference in New Issue
Block a user