Files
2026-07-13 13:12:33 +08:00

224 lines
7.2 KiB
Python

from __future__ import annotations
import json
import httpx
import pytest
from opensquilla.provider.audio import (
ElevenLabsAudioProductionProvider,
ElevenLabsSharedVoicesRequest,
ElevenLabsSpeechToTextRequest,
ElevenLabsTextToSpeechRequest,
MusicGenerationRequest,
VoiceCloneRequest,
)
@pytest.mark.anyio
async def test_elevenlabs_text_to_speech_posts_json_and_returns_audio() -> None:
requests: list[httpx.Request] = []
async def handler(request: httpx.Request) -> httpx.Response:
requests.append(request)
assert request.url.path == "/v1/text-to-speech/voice_123"
assert request.url.params["output_format"] == "mp3_44100_128"
assert request.headers["xi-api-key"] == "el-test"
payload = json.loads(request.content)
assert payload == {
"text": "hello",
"model_id": "eleven_multilingual_v2",
"language_code": "zh",
"voice_settings": {
"stability": 0.65,
"similarity_boost": 0.8,
"style": 0.0,
"use_speaker_boost": True,
"speed": 0.92,
},
}
return httpx.Response(
200,
content=b"speech-audio",
headers={"Content-Type": "audio/mpeg", "X-Generation-Id": "gen_123"},
)
provider = ElevenLabsAudioProductionProvider(
api_key="el-test",
transport=httpx.MockTransport(handler),
)
result = await provider.text_to_speech(
ElevenLabsTextToSpeechRequest(
text="hello",
voice="voice_123",
model_id="eleven_multilingual_v2",
output_format="mp3_44100_128",
language_code="zh",
voice_settings={
"stability": 0.65,
"similarity_boost": 0.8,
"style": 0.0,
"use_speaker_boost": True,
"speed": 0.92,
},
)
)
assert len(requests) == 1
assert result.audio_bytes == b"speech-audio"
assert result.provider == "elevenlabs"
assert result.voice == "voice_123"
assert result.mime_type == "audio/mpeg"
assert result.generation_id == "gen_123"
@pytest.mark.anyio
async def test_elevenlabs_clone_voice_posts_multipart_sample() -> None:
async def handler(request: httpx.Request) -> httpx.Response:
assert request.url.path == "/v1/voices/add"
body = request.content
assert b"sample.mp3" in body
assert b"voice sample" in body
assert b"Demo voice" in body
return httpx.Response(200, json={"voice_id": "voice_new", "name": "Demo voice"})
provider = ElevenLabsAudioProductionProvider(
api_key="el-test",
transport=httpx.MockTransport(handler),
)
result = await provider.clone_voice(
VoiceCloneRequest(
sample_audio_bytes=b"voice sample",
sample_filename="sample.mp3",
sample_mime_type="audio/mpeg",
name="Demo voice",
)
)
assert result.provider == "elevenlabs"
assert result.voice_id == "voice_new"
assert result.name == "Demo voice"
@pytest.mark.anyio
async def test_elevenlabs_generate_music_posts_prompt_and_returns_audio() -> None:
async def handler(request: httpx.Request) -> httpx.Response:
assert request.url.path == "/v1/music"
assert request.url.params["output_format"] == "mp3_44100_128"
assert request.headers["xi-api-key"] == "el-test"
payload = json.loads(request.content)
assert payload == {
"prompt": "cinematic intro",
"model_id": "music_v1",
"force_instrumental": True,
"music_length_ms": 12000,
}
return httpx.Response(200, content=b"music-audio", headers={"Content-Type": "audio/mpeg"})
provider = ElevenLabsAudioProductionProvider(
api_key="el-test",
transport=httpx.MockTransport(handler),
)
result = await provider.generate_music(
MusicGenerationRequest(
prompt="cinematic intro",
model_id="music_v1",
output_format="mp3_44100_128",
duration_seconds=12,
)
)
assert result.audio_bytes == b"music-audio"
assert result.model == "music_v1"
assert result.response_format == "mp3_44100_128"
@pytest.mark.anyio
async def test_elevenlabs_transcribe_audio_posts_multipart_and_returns_text() -> None:
async def handler(request: httpx.Request) -> httpx.Response:
assert request.url.path == "/v1/speech-to-text"
assert request.headers["xi-api-key"] == "el-test"
body = request.content
assert b"model_id" in body
assert b"scribe_v2" in body
assert b"voice.webm" in body
assert b"audio/webm" in body
assert b"spoken bytes" in body
return httpx.Response(
200,
json={
"text": "请帮我生成一段语音",
"language_code": "zh",
"language_probability": 0.97,
"words": [{"text": "请", "start": 0, "end": 0.2}],
},
)
provider = ElevenLabsAudioProductionProvider(
api_key="el-test",
transport=httpx.MockTransport(handler),
)
result = await provider.transcribe_audio(
ElevenLabsSpeechToTextRequest(
audio_bytes=b"spoken bytes",
filename="voice.webm",
mime_type="audio/webm",
model_id="scribe_v2",
)
)
assert result.provider == "elevenlabs"
assert result.model == "scribe_v2"
assert result.text == "请帮我生成一段语音"
assert result.language_code == "zh"
assert result.language_probability == 0.97
assert result.words[0]["text"] == "请"
@pytest.mark.anyio
async def test_elevenlabs_search_shared_voices_filters_language_and_accent() -> None:
async def handler(request: httpx.Request) -> httpx.Response:
assert request.url.path == "/v1/shared-voices"
assert request.url.params["language"] == "zh"
assert request.url.params["accent"] == "beijing mandarin"
assert request.url.params["page_size"] == "3"
assert request.headers["xi-api-key"] == "el-test"
return httpx.Response(
200,
json={
"voices": [
{
"name": "Mandarin Narrator",
"voice_id": "voice_zh",
"public_owner_id": "owner_123",
"language": "zh",
"accent": "beijing mandarin",
"gender": "female",
"category": "professional",
}
],
"has_more": False,
},
)
provider = ElevenLabsAudioProductionProvider(
api_key="el-test",
transport=httpx.MockTransport(handler),
)
result = await provider.search_shared_voices(
ElevenLabsSharedVoicesRequest(
language="zh",
accent="beijing mandarin",
page_size=3,
)
)
assert result.provider == "elevenlabs"
assert result.voices[0]["voice_id"] == "voice_zh"
assert result.raw["has_more"] is False