完善设备端体验与微信校验支持
This commit is contained in:
215
talkingq-url/tests/test_parent_voice_mp3_normalization.py
Normal file
215
talkingq-url/tests/test_parent_voice_mp3_normalization.py
Normal file
@@ -0,0 +1,215 @@
|
||||
from datetime import datetime, timezone
|
||||
from types import SimpleNamespace
|
||||
|
||||
import pytest
|
||||
|
||||
from banban.dao.im import ConversationMessageCreateResult
|
||||
from banban.schemas.im import ChildConversationMessageItem
|
||||
from banban.service.im import ImService
|
||||
from banban.service.message_audio_storage import StoredMessageAudio
|
||||
from utils.audio_transcode import infer_audio_source_format, prepare_audio_as_mp3
|
||||
|
||||
|
||||
def test_infer_audio_source_format_distinguishes_aac_from_mp3_frame_sync():
|
||||
assert infer_audio_source_format(b"\xff\xf1P\x80\x00\x1f\xfc") == "aac"
|
||||
assert infer_audio_source_format(b"\xff\xfb\x90\x64" + b"\x00" * 32) == "mp3"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_prepare_audio_as_mp3_keeps_mp3_without_transcoding(monkeypatch):
|
||||
async def fail_transcode(*args, **kwargs):
|
||||
raise AssertionError("mp3 upload should not be transcoded")
|
||||
|
||||
monkeypatch.setattr("utils.audio_transcode.transcode_audio_to_mp3", fail_transcode)
|
||||
|
||||
original = b"ID3" + b"\x00" * 32
|
||||
prepared = await prepare_audio_as_mp3(
|
||||
original,
|
||||
filename="voice.aac",
|
||||
content_type="audio/aac",
|
||||
)
|
||||
|
||||
assert prepared.content == original
|
||||
assert prepared.mime_type == "audio/mpeg"
|
||||
assert prepared.extension == "mp3"
|
||||
assert prepared.size_bytes == len(original)
|
||||
assert prepared.source_format == "mp3"
|
||||
assert prepared.transcoded is False
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_prepare_audio_as_mp3_transcodes_aac_upload(monkeypatch):
|
||||
calls = []
|
||||
|
||||
async def fake_transcode(audio_data, **kwargs):
|
||||
calls.append({"audio_data": audio_data, **kwargs})
|
||||
return b"ID3 converted"
|
||||
|
||||
monkeypatch.setattr("utils.audio_transcode.transcode_audio_to_mp3", fake_transcode)
|
||||
|
||||
original = b"\xff\xf1P\x80\x00\x1f\xfc"
|
||||
prepared = await prepare_audio_as_mp3(
|
||||
original,
|
||||
filename="voice.aac",
|
||||
content_type="audio/aac",
|
||||
)
|
||||
|
||||
assert prepared.content == b"ID3 converted"
|
||||
assert prepared.mime_type == "audio/mpeg"
|
||||
assert prepared.extension == "mp3"
|
||||
assert prepared.size_bytes == len(b"ID3 converted")
|
||||
assert prepared.source_format == "aac"
|
||||
assert prepared.original_mime_type == "audio/aac"
|
||||
assert prepared.original_extension == "aac"
|
||||
assert prepared.transcoded is True
|
||||
assert calls == [
|
||||
{
|
||||
"audio_data": original,
|
||||
"source_format": "aac",
|
||||
"source_suffix": ".aac",
|
||||
"session_device_id": "system",
|
||||
"session_id": "audio_transcode",
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_parent_voice_upload_stores_and_queues_mp3_for_device(monkeypatch):
|
||||
service = ImService()
|
||||
uploaded = []
|
||||
pending_messages = []
|
||||
duration_jobs = []
|
||||
|
||||
async def fake_assert_parent_child_access(**kwargs):
|
||||
return {"child_id": kwargs["child_id"], "child_name": "child"}
|
||||
|
||||
async def fake_get_child_binding(child_id, parent_user_id):
|
||||
return {"device_id": "TalkingQ_XQSN00001007"}
|
||||
|
||||
async def fake_upload_audio(**kwargs):
|
||||
uploaded.append(kwargs)
|
||||
return StoredMessageAudio(
|
||||
file_key="messages/audio/parent-4/2026/06/11/converted.mp3",
|
||||
public_url="https://cos.example/messages/audio/parent-4/converted.mp3",
|
||||
)
|
||||
|
||||
async def fake_create_parent_child_message(*, parent_user_id, child_id, payload):
|
||||
message = ChildConversationMessageItem(
|
||||
id=181,
|
||||
conversation_id=11,
|
||||
seq=1,
|
||||
sender_type="parent",
|
||||
sender_id=str(parent_user_id),
|
||||
receiver_type="child",
|
||||
receiver_id=str(child_id),
|
||||
content_type=payload.content_type,
|
||||
content_text=payload.content_text,
|
||||
content_json=payload.content_json,
|
||||
media_file_key=payload.media_file_key,
|
||||
media_duration_ms=payload.media_duration_ms,
|
||||
media_mime_type=payload.media_mime_type,
|
||||
media_size_bytes=payload.media_size_bytes,
|
||||
media_transcript_text=payload.media_transcript_text,
|
||||
client_msg_id=payload.client_msg_id,
|
||||
sender_name_snapshot="parent",
|
||||
sender_avatar_snapshot=None,
|
||||
receiver_name_snapshot="child",
|
||||
receiver_avatar_snapshot=None,
|
||||
ext_json=payload.ext_json,
|
||||
created_at=datetime.now(timezone.utc),
|
||||
)
|
||||
return ConversationMessageCreateResult(
|
||||
idempotent=False,
|
||||
conversation_id=11,
|
||||
conversation_type=2,
|
||||
message=message,
|
||||
)
|
||||
|
||||
async def fake_get_raw_message_media_file_key(**kwargs):
|
||||
return "messages/audio/parent-4/2026/06/11/converted.mp3"
|
||||
|
||||
async def fake_get_device_audio_url(file_key_or_url, *, device_id=None):
|
||||
assert file_key_or_url.endswith(".mp3")
|
||||
assert device_id == "TalkingQ_XQSN00001007"
|
||||
return "http://127.0.0.1:8080/device-audio/converted.mp3"
|
||||
|
||||
async def fake_add_pending_message(**kwargs):
|
||||
pending_messages.append(kwargs)
|
||||
|
||||
async def fake_schedule_message_media_duration_parse(**kwargs):
|
||||
duration_jobs.append(kwargs)
|
||||
|
||||
async def fake_prepare_audio_as_mp3(content, **kwargs):
|
||||
assert content == b"\xff\xf1 aac"
|
||||
assert kwargs["filename"] == "voice.aac"
|
||||
assert kwargs["content_type"] == "audio/aac"
|
||||
return SimpleNamespace(
|
||||
content=b"ID3 converted mp3",
|
||||
mime_type="audio/mpeg",
|
||||
extension="mp3",
|
||||
size_bytes=len(b"ID3 converted mp3"),
|
||||
source_format="aac",
|
||||
original_mime_type="audio/aac",
|
||||
original_extension="aac",
|
||||
transcoded=True,
|
||||
)
|
||||
|
||||
monkeypatch.setattr(service, "assert_parent_child_access", fake_assert_parent_child_access)
|
||||
monkeypatch.setattr("banban.service.im.binding_service.get_child_binding", fake_get_child_binding)
|
||||
monkeypatch.setattr(service.audio_storage, "upload_audio", fake_upload_audio)
|
||||
monkeypatch.setattr(service, "create_parent_child_message", fake_create_parent_child_message)
|
||||
monkeypatch.setattr(service, "_get_raw_message_media_file_key", fake_get_raw_message_media_file_key)
|
||||
monkeypatch.setattr("banban.service.im.device_audio_cache_service.get_device_audio_url", fake_get_device_audio_url)
|
||||
monkeypatch.setattr("banban.service.im.pending_voice_message_service.add_pending_message", fake_add_pending_message)
|
||||
monkeypatch.setattr(service, "schedule_message_media_duration_parse", fake_schedule_message_media_duration_parse)
|
||||
monkeypatch.setattr("banban.service.im.prepare_audio_as_mp3", fake_prepare_audio_as_mp3)
|
||||
|
||||
result = await service.create_parent_child_voice_message(
|
||||
parent_user_id=4,
|
||||
child_id=7,
|
||||
filename="voice.aac",
|
||||
content_type="audio/aac",
|
||||
content=b"\xff\xf1 aac",
|
||||
media_duration_ms=1234,
|
||||
media_transcript_text=None,
|
||||
client_msg_id="client-1",
|
||||
ext_json={
|
||||
"message_kind": "leave_message",
|
||||
"source": "parent_weapp_voice",
|
||||
},
|
||||
)
|
||||
|
||||
assert result.message.media_file_key.endswith(".mp3")
|
||||
assert result.message.media_mime_type == "audio/mpeg"
|
||||
assert result.message.media_size_bytes == len(b"ID3 converted mp3")
|
||||
assert result.message.ext_json["message_kind"] == "leave_message"
|
||||
assert result.message.ext_json["normalized_audio_format"] == "mp3"
|
||||
assert result.message.ext_json["source_audio_format"] == "aac"
|
||||
assert result.message.ext_json["audio_transcoded"] is True
|
||||
|
||||
assert uploaded == [
|
||||
{
|
||||
"device_id": "parent-4",
|
||||
"content": b"ID3 converted mp3",
|
||||
"content_type": "audio/mpeg",
|
||||
"extension": "mp3",
|
||||
}
|
||||
]
|
||||
assert pending_messages == [
|
||||
{
|
||||
"target_device_id": "TalkingQ_XQSN00001007",
|
||||
"sender_device_id": None,
|
||||
"im_message_id": 181,
|
||||
"media_file_key": "messages/audio/parent-4/2026/06/11/converted.mp3",
|
||||
"audio_url": "http://127.0.0.1:8080/device-audio/converted.mp3",
|
||||
"source": "parent_child_voice",
|
||||
}
|
||||
]
|
||||
assert duration_jobs == [
|
||||
{
|
||||
"message_id": 181,
|
||||
"audio_data": b"ID3 converted mp3",
|
||||
"mime_type": "audio/mpeg",
|
||||
"source": "parent_weapp_voice",
|
||||
}
|
||||
]
|
||||
Reference in New Issue
Block a user