models

qwen-audio-3.0-realtime-plus

Markdown · JSON

qwen-audio-3.0-realtime-plus

Модель живого голосового диалога, которая принимает речь и текст и отвечает голосом или текстом. Рассчитана на естественный темп общения и взаимодействие с инструментами.

О модели

Описание раскрывает возможности модели. Доступные в Ailoot входные данные, результаты и параметры выбранного метода перечислены ниже.

Qwen-Audio-3.0-Realtime-Plus — модель Alibaba для живого голосового диалога. Она принимает речь и текст, отвечает аудио и текстом и поддерживает двусторонний разговор с естественным обменом репликами. Звук можно передавать и получать по частям, поэтому взаимодействие развивается в ходе разговора.

Когда собеседник закончил мысль

Предусмотрены несколько способов определять границы реплики: по звуковой активности, по смысловой завершённости и через явное управление. У производителя режим выбирают до передачи первого аудио; для его изменения после начала разговора требуется новое соединение. Поддержка этого управления определяется выбранным методом. Смысловой режим учитывает паузы и заполнители речи: краткое замешательство не обязательно означает, что пользователь завершил мысль. Новая речь пользователя может прервать формируемый ответ, чтобы разговор продолжился с учётом следующей реплики. В смысловом режиме можно ориентировать распознавание на речевой образец выбранного собеседника, чтобы меньше отвлекаться на чужие голоса и фоновый шум.

Инструкции определяют роль помощника и стиль общения. Голосовая подача может учитывать тон, темп и эмоцию; для версии 3.0 предусмотрены пять системных голосов и голоса по речевому образцу. Модель поддерживает 11 языков, включая русский, а также указанные производителем китайские диалектные варианты. У производителя голос задаётся при первом обновлении настроек сессии; последующая передача нового голоса в том же разговоре игнорируется. Эти настройки требуют поддержки выбранного способа обращения.

Инструменты и история разговора

Поддерживается вызов функций. Модель формирует нужное действие, подключённое приложение выполняет его и возвращает результат в диалог. Это позволяет строить разговор вокруг фактических данных и продолжать его после выполненной операции. Голосовой помощник может опираться на результаты инструментов, сохраняя контекст беседы. Возможности производителя также включают встроенный веб-поиск, если его предоставляет выбранный метод. Веб-поиск и вызовы функций нельзя одновременно включить в одной сессии.

По умолчанию история содержит 20 ходов разговора, предусмотрен диапазон от одного до 50. Для накопленного аудио установлен предел 300 секунд; старые части истории удаляются при превышении ограничений. Это отличается от длительности отдельной реплики: история определяет, какой предыдущий материал остаётся доступным при продолжении диалога.

Текстовый контекст и звук

Формальный контекст составляет 40 960 токенов. Предельная длина входа — 16 384 токена, выхода — 8192; те же пределы входа и выхода указаны для режима рассуждения, с отдельным пределом цепочки рассуждения 1024 токена.

Для потокового звука предусмотрен одноканальный PCM с 16-битным представлением: на входе — 16 кГц, на выходе — 24 кГц. Текстовые и аудиоданные относятся к одному разговору. Визуальный вход и выдача изображений для этой конкретной модели не заявлены; её специализация — речь, текст и голосовое взаимодействие.

Ailoot · Голос в реальном времени GET /v1/realtime?model=qwen-audio-3.0-realtime-plus qwen-audio-3.0-realtime-plus

qwen-audio-3.0-realtime-plus

Alibaba /qwen-audio-3.0-realtime-plus

Начало

Модель живого голосового диалога, которая принимает речь и текст и отвечает голосом или текстом. Рассчитана на естественный темп общения и взаимодействие с инструментами.

Допустимые входные данные
Текст · Аудио
Результаты
Текст · Аудио

Доступно в Ailoot · входные данные и методы

Ailoot · Голос в реальном времени GET /v1/realtime?model=qwen-audio-3.0-realtime-plus
Входные данные
text, audio
Результат
text, audio
Выходной формат
события сессии
ПолеТипТребованиеЗначения и ограниченияПо умолчанию
Полеquery.modelТипstringТребованиеОбязательноЗначения и ограничения
qwen-audio-3.0-realtime-plus
По умолчанию—
Полеsession.input_audio_formatТипstringТребованиеНеобязательноЗначения и ограничения
pcm16, pcm
По умолчанию—
Полеsession.output_audio_formatТипstringТребованиеНеобязательноЗначения и ограничения
pcm16, pcm
По умолчанию—
Полеsession.instructionsТипstringТребованиеНеобязательноЗначения и ограничения
Объект ограничения: выбранная политика сессии
По умолчанию—
Полеsession.max_history_turnsТипintegerТребованиеНеобязательноЗначения и ограничения
Минимум: 1
Объект ограничения: выбранная политика сессии
По умолчанию—
Полеinput_audio_buffer.append.audioТипbase64_stringТребованиеОбязательноЗначения и ограничения
Входное содержимое: PCM16 моно; вход 16 kHz, выход 24 kHz; непустые данные с чётным количеством байтов
По умолчанию—
Сочетания входных материалов

realtime_text_audio

Параметры и жизненный цикл метода
ПараметрКонтракт
Параметрmaterial_typesКонтрактtext, audio
ПараметрrequiredКонтрактnull
Параметрoptional_controlsКонтрактnull
Параметрcontent_typeКонтрактWebSocket

Жизненный цикл: exact retained published method

Структуры методов и ID указаны точно; возможности поставщика рассматриваются отдельно от допуска.

Тарифы

Ставки методов Ailoot

Ailoot Голос в реальном времениGET /v1/realtime?model=qwen-audio-3.0-realtime-plus
Вход
0,0008 $ / 1K
Выход
0,0064 $ / 1K
Вход
0,0048 $ за минуту аудио
Выход
0,018 $ за минуту выходного аудио

Ailoot резервирует расчётную сумму перед запросом. После получения результата списывает итоговую плату по измеренному расходу. Для окончательного списания за потоковый ответ используется итоговая запись расхода. Как работают резервирование и расчёт →

Примеры запросов

Ailoot · Голос в реальном времени

Python WebSocket · текстPython WebSocket · аудио
# Install the documented client once: python3 -m pip install websockets
import base64, json, os, time, wave
from pathlib import Path
from websockets.sync.client import connect

key = os.environ.get("AILOOT_API_KEY", "")
if not key.strip():
    raise SystemExit("Set your AILOOT_API_KEY before connecting")
file = Path(os.environ.get("AILOOT_TEXT_FILE", ""))
if not file.is_file(): raise SystemExit("Set AILOOT_TEXT_FILE to your actual UTF-8 material")
material = file.read_text(encoding="utf-8")
if not material.strip(): raise SystemExit("Text material must not be empty")
out = Path("realtime-results")
out.mkdir(exist_ok=True)
audio, texts, complete = {}, {}, []
current_response = None
pending = False
deadline = time.monotonic() + 570  # Local client bound; lower server/session limits still apply.

def receive(ws, log):
    global current_response, pending
    left = deadline - time.monotonic()
    if left <= 0:
        raise TimeoutError("Client session limit; preserve IDs and partial results, do not replay")
    event = json.loads(ws.recv(timeout=min(60, left)))
    log.write(json.dumps(event, ensure_ascii=False) + "\n")
    log.flush()
    kind = event.get("type")
    if kind == "error":
        raise RuntimeError(json.dumps(event, ensure_ascii=False))
    if kind == "response.created":
        current_response = event["response"]["id"]
    if kind in {"response.audio.delta", "response.output_audio.delta", "response.text.delta", "response.output_text.delta", "response.audio_transcript.delta", "response.output_audio_transcript.delta", "response.text.done", "response.audio_transcript.done"}:
        identity = (event["response_id"], event["item_id"], event["output_index"], event["content_index"])
        if kind in {"response.audio.delta", "response.output_audio.delta"}:
            raw = base64.b64decode(event["delta"], validate=True)
            if len(raw) % 2: raise ValueError("Output PCM16 chunk must have an even byte length")
            audio.setdefault(identity, bytearray()).extend(raw)
        elif kind.endswith(".done"):
            texts[identity] = event.get("text", event.get("transcript", ""))
        else:
            texts[identity] = texts.get(identity, "") + event["delta"]
            print(event["delta"], end="", flush=True)
    if kind == "response.done":
        response = event["response"]
        complete.append(response)
        if current_response is None: current_response = response["id"]
        if response["id"] == current_response: pending = False
    return event

def wait_for(ws, log, kind):
    while True:
        event = receive(ws, log)
        if event.get("type") == kind: return event

def send(ws, event):
    ws.send(json.dumps(event, ensure_ascii=False))

try:
    # One exact model query; no reconnect/retry loop and no provider credentials.
    with connect("wss://api.ailoot.ai/v1/realtime?model=qwen-audio-3.0-realtime-plus", additional_headers={"Authorization": "Bearer " + key}) as ws:
        with (out / "events.jsonl").open("w", encoding="utf-8") as log:
            wait_for(ws, log, "session.created")
            send(ws, {"type":"session.update", "session":{"modalities":["audio","text"], "input_audio_format":"pcm", "output_audio_format":"pcm", "turn_detection":None}})
            wait_for(ws, log, "session.updated")
            send(ws, {"type":"conversation.item.create", "item":{"type":"message", "role":"user", "content":[{"type":"input_text", "text":material}]}})
            send(ws, {"type":"response.create"})
            pending = True
            try:
                while pending: receive(ws, log)
            except KeyboardInterrupt:
                # Cancel the actual current inference, then preserve its returned status.
                send(ws, {"type":"response.cancel"})
                while pending: receive(ws, log)
    if not complete or complete[-1].get("status") != "completed":
        raise RuntimeError("Response did not complete normally; inspect saved events and status")
finally:
    manifest = {"responses":complete, "parts":[]}
    for number, identity in enumerate(dict.fromkeys(list(audio) + list(texts))):
        record = {"response_id":identity[0], "item_id":identity[1], "output_index":identity[2], "content_index":identity[3]}
        if identity in audio:
            raw = bytes(audio[identity])
            pcm_file = out / ("audio-" + str(number) + ".pcm")
            wav_file = out / ("audio-" + str(number) + ".wav")
            pcm_file.write_bytes(raw)
            with wave.open(str(wav_file), "wb") as wav:
                wav.setnchannels(1); wav.setsampwidth(2); wav.setframerate(24000); wav.writeframes(raw)
            record.update({"pcm":str(pcm_file), "wav":str(wav_file), "sample_rate_hz":24000})
        if identity in texts:
            text_file = out / ("text-" + str(number) + ".txt")
            text_file.write_text(texts[identity], encoding="utf-8")
            record["text"] = str(text_file)
        manifest["parts"].append(record)
    (out / "results.json").write_text(json.dumps(manifest, ensure_ascii=False, indent=2), encoding="utf-8")
    print("\nSaved every received event and result in", out)
# Install the documented client once: python3 -m pip install websockets
import base64, json, os, time, wave
from pathlib import Path
from websockets.sync.client import connect

key = os.environ.get("AILOOT_API_KEY", "")
if not key.strip():
    raise SystemExit("Set your AILOOT_API_KEY before connecting")
file = Path(os.environ.get("AILOOT_AUDIO_FILE", ""))
if not file.is_file(): raise SystemExit("Set AILOOT_AUDIO_FILE to your raw PCM16 mono 16-kHz recording")
material = file.read_bytes()
if not material or len(material) % 2 or material.startswith(b"RIFF"):
    raise SystemExit("Use nonempty signed little-endian PCM16 mono 16-kHz bytes, not a WAV header")
out = Path("realtime-results")
out.mkdir(exist_ok=True)
audio, texts, complete = {}, {}, []
current_response = None
pending = False
deadline = time.monotonic() + 570  # Local client bound; lower server/session limits still apply.

def receive(ws, log):
    global current_response, pending
    left = deadline - time.monotonic()
    if left <= 0:
        raise TimeoutError("Client session limit; preserve IDs and partial results, do not replay")
    event = json.loads(ws.recv(timeout=min(60, left)))
    log.write(json.dumps(event, ensure_ascii=False) + "\n")
    log.flush()
    kind = event.get("type")
    if kind == "error":
        raise RuntimeError(json.dumps(event, ensure_ascii=False))
    if kind == "response.created":
        current_response = event["response"]["id"]
    if kind in {"response.audio.delta", "response.output_audio.delta", "response.text.delta", "response.output_text.delta", "response.audio_transcript.delta", "response.output_audio_transcript.delta", "response.text.done", "response.audio_transcript.done"}:
        identity = (event["response_id"], event["item_id"], event["output_index"], event["content_index"])
        if kind in {"response.audio.delta", "response.output_audio.delta"}:
            raw = base64.b64decode(event["delta"], validate=True)
            if len(raw) % 2: raise ValueError("Output PCM16 chunk must have an even byte length")
            audio.setdefault(identity, bytearray()).extend(raw)
        elif kind.endswith(".done"):
            texts[identity] = event.get("text", event.get("transcript", ""))
        else:
            texts[identity] = texts.get(identity, "") + event["delta"]
            print(event["delta"], end="", flush=True)
    if kind == "response.done":
        response = event["response"]
        complete.append(response)
        if current_response is None: current_response = response["id"]
        if response["id"] == current_response: pending = False
    return event

def wait_for(ws, log, kind):
    while True:
        event = receive(ws, log)
        if event.get("type") == kind: return event

def send(ws, event):
    ws.send(json.dumps(event, ensure_ascii=False))

try:
    # One exact model query; no reconnect/retry loop and no provider credentials.
    with connect("wss://api.ailoot.ai/v1/realtime?model=qwen-audio-3.0-realtime-plus", additional_headers={"Authorization": "Bearer " + key}) as ws:
        with (out / "events.jsonl").open("w", encoding="utf-8") as log:
            wait_for(ws, log, "session.created")
            send(ws, {"type":"session.update", "session":{"modalities":["audio","text"], "input_audio_format":"pcm", "output_audio_format":"pcm", "turn_detection":None}})
            wait_for(ws, log, "session.updated")
            for offset in range(0, len(material), 640):
                send(ws, {"type":"input_audio_buffer.append", "audio":base64.b64encode(material[offset:offset+640]).decode("ascii")})
                time.sleep(0.02)
            send(ws, {"type":"input_audio_buffer.commit"})
            wait_for(ws, log, "input_audio_buffer.committed")
            send(ws, {"type":"response.create"})
            pending = True
            try:
                while pending: receive(ws, log)
            except KeyboardInterrupt:
                # Cancel the actual current inference, then preserve its returned status.
                send(ws, {"type":"response.cancel"})
                while pending: receive(ws, log)
    if not complete or complete[-1].get("status") != "completed":
        raise RuntimeError("Response did not complete normally; inspect saved events and status")
finally:
    manifest = {"responses":complete, "parts":[]}
    for number, identity in enumerate(dict.fromkeys(list(audio) + list(texts))):
        record = {"response_id":identity[0], "item_id":identity[1], "output_index":identity[2], "content_index":identity[3]}
        if identity in audio:
            raw = bytes(audio[identity])
            pcm_file = out / ("audio-" + str(number) + ".pcm")
            wav_file = out / ("audio-" + str(number) + ".wav")
            pcm_file.write_bytes(raw)
            with wave.open(str(wav_file), "wb") as wav:
                wav.setnchannels(1); wav.setsampwidth(2); wav.setframerate(24000); wav.writeframes(raw)
            record.update({"pcm":str(pcm_file), "wav":str(wav_file), "sample_rate_hz":24000})
        if identity in texts:
            text_file = out / ("text-" + str(number) + ".txt")
            text_file.write_text(texts[identity], encoding="utf-8")
            record["text"] = str(text_file)
        manifest["parts"].append(record)
    (out / "results.json").write_text(json.dumps(manifest, ensure_ascii=False, indent=2), encoding="utf-8")
    print("\nSaved every received event and result in", out)

Получить и сохранить результаты

Ailoot · Голос в реальном времени

события сессии

Сохраняйте все готовые результаты

Сохраняйте каждый полностью полученный ответ, файл и элемент содержимого.

Соберите каждый возвращённый фрагмент аудио и текстовый результат или событие для каждого фактического ID ответа.

Если нужно проверить исходный ответ

Сохраняйте фактические ID сессии, ответа, событий и подтверждающие записи.

Ошибки и дальнейшие шаги
ОтветУсловиеСледующий шаг
Ответ426 · invalid_request_errorУсловиеБез переключения протокола на WebSocketСледующий шагИспользуйте клиент WebSocket с Upgrade: websocket.

Псевдонимы

Псевдонимы моделей

Ailoot qwen-audio-3.0-realtime-plus

Псевдонимы путей метода

Используйте пути методов, указанные выше.

Связанные ID для вызова

qwen-audio-3.0-realtime-plus

FAQ · qwen-audio-3.0-realtime-plus
Какие входные данные и результаты доступны?

GET /v1/realtime?model=qwen-audio-3.0-realtime-plus · qwen-audio-3.0-realtime-plus: text, audio → text, audio

Какие ограничения действуют?

GET /v1/realtime?model=qwen-audio-3.0-realtime-plus · qwen-audio-3.0-realtime-plus: session.max_history_turns.minimum: 1

Подробнее

Подключите Ailoot к Claude Code, OpenCode, Hermes или своему приложению.

Компания и портфель её проектов

Компания и портфель её проектов: миллионы клиентов; продажи на миллиарды ежемесячно.

Покупайте токены со скидкой.

Скидка по подписке для регулярной работы. Промокоды — до 50% на покупку токенов.

Подписка
Выберите тариф со скидкой для своих регулярных запросов.
Промокод до 50%
Введите код при покупке. Цена пересчитается с учётом действующей акции.
Расходы в истории
Модель, токены и сумма сохраняются для каждого запроса.

Выбрать подписку · Посмотреть цены моделей

Подключайте API к продукту, который вы продаёте.

SaaS, приложения и боты — по оферте и лицензионному договору Ailoot. Для перепродажи запросите реселлерскую лицензию.

Коммерческое приложение
Встраивайте генерацию текста, картинок, видео и звука в платные функции своего сервиса.
Лицензия для реселлера
Пришлите описание проекта и схему доступа. Запросите письменные условия использования и перепродажи.
Документы на сайте
Оферта, лицензионный договор и политика обработки данных доступны до подключения.

Запросить реселлерскую лицензию · Оферта и лицензионный договор