У меня есть функция узла, которая принимает аудиофайл, записанный на мобильном устройстве, и возвращает транскрипцию и временные смещения для каждого слова в транскрипции. Кажется, все работает хорошо, за исключением того, что временные сдвиги связаны с неправильными словами.
Вот моя функция:
const speech = require('@google-cloud/speech');
const functions = require('firebase-functions');
const admin = require('firebase-admin');
const path = require('path');
const os = require('os');
const fs = require('fs');
const ffmpegPath = require('@ffmpeg-installer/ffmpeg').path;
const ffmpeg = require('fluent-ffmpeg');
admin.initializeApp();
export const transcribeAudio = functions.https.onRequest(async (req, res) => {
const { name, fullPath } = req.query;
const bucket = admin.storage().bucket('audio-test.appspot.com');
const tempFilePath = path.join(os.tmpdir(), name);
const targetTempFilePath = path.join(os.tmpdir(), `${name}-converted.mp3`);
await bucket.file(fullPath).download({ destination: tempFilePath }).catch(console.warn);
const command = ffmpeg(tempFilePath)
.setFfmpegPath(ffmpegPath)
.format('mp3')
.output(targetTempFilePath);
await new Promise((resolve, reject) => command.on('end', resolve).on('error', reject).run()).catch(console.warn);
const file = fs.readFileSync(targetTempFilePath);
const audioBytes = file.toString('base64');
const audio = { content: audioBytes };
const client = new speech.SpeechClient();
const config = {
encoding: 'MP3',
sampleRateHertz: 16000,
languageCode: 'en-US',
enableWordTimeOffsets: true,
enableAutomaticPunctuation: true,
};
const request = {
audio: audio,
config: config,
};
const [response] = await client.recognize(request).catch(console.warn);
res.send(response);
fs.unlinkSync(tempFilePath);
fs.unlinkSync(targetTempFilePath);
});
И вот json, возвращенный из этого function:
{
"results": Array [
Object {
"alternatives": Array [
Object {
"confidence": 0.9800227284431458,
"transcript": "How much wood would a woodchuck chuck if a woodchuck could chuck wood?",
"words": Array [
Object {
"endTime": Object {
"nanos": 100000000,
"seconds": "4",
},
"speakerTag": 0,
"startTime": Object {
"nanos": 700000000,
"seconds": "3",
},
"word": "How",
},
Object {
"endTime": Object {
"nanos": 400000000,
"seconds": "4",
},
"speakerTag": 0,
"startTime": Object {
"nanos": 100000000,
"seconds": "4",
},
"word": "much",
},
Object {
"endTime": Object {
"nanos": 700000000,
"seconds": "4",
},
"speakerTag": 0,
"startTime": Object {
"nanos": 400000000,
"seconds": "4",
},
"word": "wood",
},
Object {
"endTime": Object {
"nanos": 800000000,
"seconds": "4",
},
"speakerTag": 0,
"startTime": Object {
"nanos": 700000000,
"seconds": "4",
},
"word": "would",
},
Object {
"endTime": Object {
"nanos": 0,
"seconds": "5",
},
"speakerTag": 0,
"startTime": Object {
"nanos": 800000000,
"seconds": "4",
},
"word": "a",
},
Object {
"endTime": Object {
"nanos": 100000000,
"seconds": "5",
},
"speakerTag": 0,
"startTime": Object {
"nanos": 0,
"seconds": "5",
},
"word": "woodchuck",
},
Object {
"endTime": Object {
"nanos": 600000000,
"seconds": "5",
},
"speakerTag": 0,
"startTime": Object {
"nanos": 100000000,
"seconds": "5",
},
"word": "chuck",
},
Object {
"endTime": Object {
"nanos": 200000000,
"seconds": "6",
},
"speakerTag": 0,
"startTime": Object {
"nanos": 600000000,
"seconds": "5",
},
"word": "if",
},
Object {
"endTime": Object {
"nanos": 400000000,
"seconds": "6",
},
"speakerTag": 0,
"startTime": Object {
"nanos": 200000000,
"seconds": "6",
},
"word": "a",
},
Object {
"endTime": Object {
"nanos": 700000000,
"seconds": "6",
},
"speakerTag": 0,
"startTime": Object {
"nanos": 400000000,
"seconds": "6",
},
"word": "woodchuck",
},
Object {
"endTime": Object {
"nanos": 0,
"seconds": "9",
},
"speakerTag": 0,
"startTime": Object {
"nanos": 700000000,
"seconds": "6",
},
"word": "could",
},
Object {
"endTime": Object {
"nanos": 200000000,
"seconds": "9",
},
"speakerTag": 0,
"startTime": Object {
"nanos": 0,
"seconds": "9",
},
"word": "chuck",
},
Object {
"endTime": Object {
"nanos": 600000000,
"seconds": "9",
},
"speakerTag": 0,
"startTime": Object {
"nanos": 200000000,
"seconds": "9",
},
"word": "wood?",
},
],
},
],
"channelTag": 0,
},
],
}
В приведенном выше примере я намеренно вытащил слово «сурок» во второй раз, когда сказал его. Если вы посмотрите на смещения, кажется, что времена для этого слова были применены к следующему слову «мог», которое я сказал гораздо быстрее в записи. Любое понимание того, почему это происходит, было бы очень полезно. Спасибо!