Как получить доступ к аудиопотоку, записанному в Microsoft Speech SDK - PullRequest
1 голос
/ 04 апреля 2020

Я транскрибирую поток микрофонов с помощью Microsoft Speech SDK для JavaScript. И запись, и транскрипция выполняются с использованием Speech SDK, и я не смог найти способ доступа и сохранения записанного аудиофайла после завершения записи.

Код для создания рекордера и записи

recognizer = new SpeechSDK.SpeechRecognizer(speechConfig, audioConfig);
// to start the recording
recognizer.startContinuousRecognitionAsync(
    () => {
      portFromCS.postMessage({ type: "started", data: "" });
    },
    err => {
      recognizer.close();
    },
  );
// used after user input to stop the recording
recognizer.stopContinuousRecognitionAsync(
    () => {
      window.console.log("successfully stopped");
      // TODO: somehow need to save the file
    },
    err => {
      window.console.log("error on stop", err);
    },
  );

Документация довольно плохая, и мне не удалось найти встроенный способ доступа к необработанному аудио с помощью их SDK. Является ли мой единственный вариант иметь два аудиопотока для записи и сохранить файл, используя отдельный поток записи? Каковы последствия этого?

1 Ответ

0 голосов
/ 06 апреля 2020

SDK не сохраняет аудио и не имеет встроенных функций для этого.

В версии 1.11.0 был добавлен новый API к объекту соединения, чтобы вы могли видеть сообщения, отправленные на служба, из которой вы можете извлечь аудио и собрать файл волны самостоятельно.

Вот несколько машинописных текстов, которые делают это:

import * as SpeechSdk from "microsoft-cognitiveservices-speech-sdk";
import * as fs from "fs";

const filename: string = "input.wav";
const outputFileName: string = "out.wav";
const subscriptionKey: string = "<SUBSCRIPTION_KEY>";
const region: string = "<SUBSCRIPTION_REGION>";

const speechConfig: SpeechSdk.SpeechConfig = SpeechSdk.SpeechConfig.fromSubscription(subscriptionKey, region);

// Load the audio from a file, alternately you could use 
// const audioConfig:SpeechSdk.AudioConfig = SpeechSdk.AudioConfig.fromDefaultMicrophone() in a browser();
const fileContents: Buffer = fs.readFileSync(filename);
const inputStream: SpeechSdk.PushAudioInputStream = SpeechSdk.AudioInputStream.createPushStream();
const audioConfig: SpeechSdk.AudioConfig = SpeechSdk.AudioConfig.fromStreamInput(inputStream);
inputStream.write(fileContents);
inputStream.close();

const r: SpeechSdk.SpeechRecognizer = new SpeechSdk.SpeechRecognizer(speechConfig, audioConfig);
const con: SpeechSdk.Connection = SpeechSdk.Connection.fromRecognizer(r);

let wavFragmentCount: number = 0;

const wavFragments: { [id: number]: ArrayBuffer; } = {};

con.messageSent = (args: SpeechSdk.ConnectionMessageEventArgs): void => {
    // Only record outbound audio mesages that have data in them.
    if (args.message.path === "audio" && args.message.isBinaryMessage && args.message.binaryMessage !== null) {
        wavFragments[wavFragmentCount++] = args.message.binaryMessage;
    }
};

r.recognizeOnceAsync((result: SpeechSdk.SpeechRecognitionResult) => {
    // Find the length of the audio sent.
    let byteCount: number = 0;
    for (let i: number = 0; i < wavFragmentCount; i++) {
        byteCount += wavFragments[i].byteLength;
    }

    // Output array.
    const sentAudio: Uint8Array = new Uint8Array(byteCount);

    byteCount = 0;
    for (let i: number = 0; i < wavFragmentCount; i++) {
        sentAudio.set(new Uint8Array(wavFragments[i]), byteCount);
        byteCount += wavFragments[i].byteLength;
    }

    // Set the file size in the wave header:
    const view = new DataView(sentAudio.buffer);
    view.setUint32(4, byteCount, true);
    view.setUint32(40, byteCount, true);

    // Write the audio back to disk.
    fs.writeFileSync(outputFileName, sentAudio);
    r.close();
});

Он загружается из файла, чтобы я мог проверить в NodeJS вместо браузера, но основная часть та же.

...