Транскрибація у мобільному додатку з Deepgram Nova-2

Коли користувач говорить у мікрофон, а текст з'являється на екрані із затримкою менше секунди, це змінює сприйняття продукту. Ми інтегруємо Deepgram Nova-2 у мобільні застосунки, налаштовуючи потокову транскрибацію в реальному часі через WebSocket. Наша команда реалізує проєкт під ключ — від аудиту до впровадження та подальшої підтримки, забезпечуючи стабільну роботу й живі субтитри без зриву термінів.

Розробка та підтримка будь-яких видів мобільних додатків:

Інформаційні та розважальні мобільні програми
Новинки, ігри, довідники, онлайн-каталоги, погодні, фітнес та здоров'я, туристичні, освітні, соціальні мережі та месенджери, квіз, блоги та подкасти, форуми, агрегатори
Мобільні програми електронної комерції
Інтернет-магазини, B2B-додатки, маркетплейси, онлайн-обмінники, кешбек-сервіси, біржі, дропшиппінг-платформи, програми лояльності, доставка їжі та товарів, платіжні системи
Мобільні програми для управління бізнес-процесами
CRM-системи, ERP-системи, управління проектами, інструменти для команди продажів, облік фінансів, управління виробництвом, логістика та доставка, управління персоналом, системи моніторингу даних
Мобільні програми електронних послуг
Дошки оголошень, онлайн-школи, онлайн-кінотеатри, платформи надання електронних послуг, платформи кешбеку, відеохостинги, тематичні портали, платформи онлайн-бронювання та запису, платформи онлайн-торгівлі

Це лише деякі з типів мобільних додатків, з якими ми працюємо, і кожен із них може мати свої специфічні особливості та функціональність, а також бути адаптованим під конкретні потреби та цілі клієнта.

Послуги, які ми пропонуємо
Показано 1 з 1Усі 1734 послуг
Транскрибація у мобільному додатку з Deepgram Nova-2
Середній
~3-5 днів
Часті запитання

Уявіть: користувач говорить у мікрофон, а текст з'являється на екрані із затримкою менше півсекунди. Це нетривіальне інженерне завдання, але з Deepgram Nova-2 воно вирішується. Модель дає медіанну затримку близько 300 мс і WER близько 5% на російській мові. Такі показники недоступні класичним batch-рішенням. У цій статті розберемо, як налаштувати WebSocket-транскрибацію на iOS та Android, які параметри критичні та як уникнути типових помилок.

Типові труднощі — нестабільне з'єднання, дублювання interim-результатів, неправильна конфігурація аудіокодека. Наша команда з 10+ річним досвідом впровадження ASR (5+ років на ринку, понад 50 проектів) гарантує стабільне з'єднання та низьку затримку. На реальному проекті клієнт скаржився на дублювання interim: кожне нове слово додавалося до попереднього. Після впровадження патерну заміни буфера проблема зникла повністю.

Порівняння: Deepgram Nova-2 кращий за Whisper у 6-10 разів за швидкістю стримінгу.

Які параметри впливають на якість транскрибації?

Deepgram Nova-2 забезпечує низьку затримку на стримінгу: медіана близько 300 мс від кінця фрази до тексту. Whisper такого не вміє в принципі — він синхронний. Якщо задача «користувач говорить — текст з'являється на екрані» із затримкою менше секунди, це Deepgram.

Характеристика Deepgram Nova-2 Whisper (синхронний)
Затримка фіналу 300–500 мс 2–5 секунд
Стримінг Асинхронний, потоковий Синхронний, batch
Interim результати Так Ні
Підтримка російської Відмінно Добре
Ціна (за годину) $0.01/хв Безкоштовно (self-hosted)

Для мобільного сценарію Deepgram виграє у 6–10 разів за швидкістю. Крім того, Nova-2 показує WER ≤5% на російській мові, у той час як Whisper large-v2 — близько 7%.

Як налаштувати протокол підключення?

Deepgram працює через WebSocket. Endpoint:

wss://api.deepgram.com/v1/listen?model=nova-2&language=ru&encoding=linear16&sample_rate=16000&channels=1&interim_results=true 

Параметри критичні: encoding=linear16 означає сирий PCM 16-bit little-endian. Будь-який інший формат без явного зазначення кодека — ризик 1008 Policy Violation. interim_results=true включає часткові результати — саме вони створюють відчуття реального часу.

iOS: AVAudioEngine + URLSessionWebSocketTask

class DeepgramStreamer {
    private var audioEngine = AVAudioEngine()
    private var webSocket: URLSessionWebSocketTask?

    func start() throws {
        let session = URLSession(configuration: .default)
        var request = URLRequest(url: URL(string: "wss://api.deepgram.com/v1/listen?model=nova-2&language=ru&encoding=linear16&sample_rate=16000&channels=1&interim_results=true")!)
        request.setValue("Token \(apiKey)", forHTTPHeaderField: "Authorization")
        webSocket = session.webSocketTask(with: request)
        webSocket?.resume()
        receiveLoop()

        let inputNode = audioEngine.inputNode
        let format = AVAudioFormat(commonFormat: .pcmFormatInt16, sampleRate: 16000, channels: 1, interleaved: false)!
        inputNode.installTap(onBus: 0, bufferSize: 4096, format: format) { buffer, _ in
            guard let channelData = buffer.int16ChannelData else { return }
            let frameLength = Int(buffer.frameLength)
            let data = Data(bytes: channelData[0], count: frameLength * 2)
            self.webSocket?.send(.data(data)) { _ in }
        }
        try audioEngine.start()
    }

    private func receiveLoop() {
        webSocket?.receive { [weak self] result in
            if case .success(let message) = result, case .string(let text) = message {
                // Decode Deepgram JSON response
                self?.handleTranscript(text)
            }
            self?.receiveLoop()
        }
    }
}

Важлива деталь: AVAudioEngine.inputNode на iOS 16+ вимагає явного запиту мікрофона через AVAudioSession.sharedInstance().requestRecordPermission. І обов'язково AVAudioSession.setCategory(.record, mode: .measurement) — режим .measurement вимикає AEC та AGC, які можуть спотворити сигнал для транскрипції.

Android: AudioRecord + OkHttp WebSocket

class DeepgramStreamer(private val apiKey: String) {
    private val client = OkHttpClient()
    private var webSocket: WebSocket? = null
    private var audioRecord: AudioRecord? = null

    fun start(onTranscript: (String, Boolean) -> Unit) {
        val request = Request.Builder()
            .url("wss://api.deepgram.com/v1/listen?model=nova-2&language=ru&encoding=linear16&sample_rate=16000&channels=1&interim_results=true")
            .header("Authorization", "Token $apiKey")
            .build()

        webSocket = client.newWebSocket(request, object : WebSocketListener() {
            override fun onMessage(webSocket: WebSocket, text: String) {
                val json = JSONObject(text)
                val channel = json.getJSONObject("channel")
                val alternatives = channel.getJSONArray("alternatives")
                val transcript = alternatives.getJSONObject(0).getString("transcript")
                val isFinal = json.getBoolean("is_final")
                if (transcript.isNotEmpty()) onTranscript(transcript, isFinal)
            }
        })

        val bufferSize = AudioRecord.getMinBufferSize(16000, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT)
        audioRecord = AudioRecord(MediaRecorder.AudioSource.MIC, 16000, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT, bufferSize)
        audioRecord?.startRecording()

        Thread {
            val buffer = ShortArray(bufferSize / 2)
            while (audioRecord?.recordingState == AudioRecord.RECORDSTATE_RECORDING) {
                val read = audioRecord!!.read(buffer, 0, buffer.size)
                if (read > 0) {
                    val byteBuffer = ByteBuffer.allocate(read * 2).order(ByteOrder.LITTLE_ENDIAN)
                    buffer.take(read).forEach { byteBuffer.putShort(it) }
                    webSocket?.send(byteBuffer.array().toByteString())
                }
            }
        }.start()
    }
}

ByteOrder.LITTLE_ENDIAN обов'язковий. Deepgram очікує LE PCM. Якщо відправити BE, транскрипція працюватиме, але з помітно гіршою якістю.

Як уникнути типових помилок при стримінгу аудіо?

  • Дублювання interim: ніколи не накопичуйте всі interim як окремі рядки. Зберігайте поточний utterance у буфері та перезаписуйте його при кожному новому interim. При is_final: true фіналізуйте буфер.
  • Втрата з'єднання: впровадьте reconnect з експоненційною затримкою (1,2,4,8 сек). Deepgram не підтримує відновлення сесії, тому після reconnect потрібно почати новий потік.
  • Неправильна частота дискретизації: використовуйте строго 16000 Гц. Вища частота збільшує трафік без виграшу в якості, нижча — погіршує розпізнавання.

Обробка interim-результатів

Deepgram повертає два типи повідомлень: з is_final: false (interim) та is_final: true (фінальний). Правильний патерн UI:

  • Interim відображаємо сірим або курсивом — користувач бачить, що йде розпізнавання.
  • При отриманні is_final: true замінюємо всі попередні interim цього utterance фінальним текстом.
  • speech_final: true означає кінець паузи — хороший момент для початку обробки фрази.

Параметри Nova-2, які змінюють якість

Параметр Значення Опис
model nova-2 Модель розпізнавання
encoding linear16 Кодування аудіо
sample_rate 16000 Частота дискретизації
interim_results true Включити часткові результати
utterance_end_ms 1000 Фіналізація паузою
diarize false Розділення дикторів
punctuate true Автоматична пунктуація
smart_format true Форматування чисел та дат
  • utterance_end_ms: 1000 — Deepgram сам фіналізує utterance після 1 секунди тиші. Корисно для диктування без явних команд «стоп».
  • diarize: true — розділення по спікерах, додає speaker у кожен word.
  • punctuate: true — автопунктуація. Без неї текст іде без крапок та ком.
  • smart_format: true — форматує числа, дати, телефони. «двадцять п'яте березня» → «25 березня».

Що входить у роботу

  • Налаштування WebSocket-підключення з авторизацією
  • Захоплення аудіо через AVAudioEngine / AudioRecord з правильним форматом
  • Обробка interim та фінальних результатів без дублювання
  • Reconnect при обриві мережі з експоненційною затримкою
  • Тестування на реальних пристроях (iOS/Android)
  • Документація та навчання команди

Процес роботи

  1. Аналіз — вивчаємо архітектуру додатку та вимоги до транскрибації
  2. Проектування — обираємо модель, протокол, параметри
  3. Реалізація — кодова інтеграція WebSocket, аудіозахоплення, UI
  4. Тестування — навантажувальне тестування, перевірка на різних пристроях і мережах
  5. Деплой — публікація в App Store та Google Play

Строки

Базова інтеграція WebSocket + AudioRecord/AVAudioEngine + вивід тексту — 4–7 днів. Додавання діаризації, обробки перемикання мережі (reconnect), фонового режиму, експорту результату — 8–14 днів.

Економія на розробці власного ASR-двигуна може досягати 70%, а вартість транскрибації становить $0.01 за хвилину аудіо. Отримайте консультацію з інтеграції Deepgram для вашого мобільного проекту. Ми проаналізуємо архітектуру, підберемо оптимальну конфігурацію та реалізуємо low-latency транскрибацію під ключ. Замовте демо-версію з низькою затримкою вже сьогодні. Зв'яжіться з нами для обговорення вашого проекту.

Інтеграція Deepgram дозволила нам скоротити затримку транскрибації з 5 секунд до 300 мс — відгук клієнта з фінансового сектору.

Наші компетенції:

Останні роботи

  • Розробка мобільного додатка для компанії FEEDME
    Розробка мобільного додатка для компанії FEEDME
    1010
  • Розробка мобільного додатку для компанії XOOMER
    Розробка мобільного додатку для компанії XOOMER
    903
  • Розробка мобільного додатку для компанії RHL
    Розробка мобільного додатку для компанії RHL
    1332
  • Розробка мобільного додатку для компанії ZIPPY
    Розробка мобільного додатку для компанії ZIPPY
    1180
  • Розробка мобільного додатку для компанії Affhome
    Розробка мобільного додатку для компанії Affhome
    1107
  • Розробка мобільного додатку для компанії FLAVORS
    Розробка мобільного додатку для компанії FLAVORS
    714