You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

AWS Transcribe流式服务报错:TypeError: e.$unknown is undefined求助

AWS Transcribe流式服务报错排查:TypeError: e.$unknown is undefined

问题描述

尝试使用AWS Transcribe流式服务,录制音频并转换为服务支持格式传入时触发以下错误:

TypeError: e.$unknown is undefined
visit models_0.js:21
fn Aws_restJson1.js:343
asyncIterator SmithyMessageEncoderStream.js:10
domande_generiche.html:107:29

原代码

import { TranscribeStreamingClient, StartStreamTranscriptionCommand } from "https://cdn.jsdelivr.net/npm/@aws-sdk/client-transcribe-streaming@latest/+esm";
let mediaRecorder;
let audioChunks = [];

const transcribeClient = new TranscribeStreamingClient({
    region: "us-east-1",
    credentials: {
        accessKeyId: "xxxxxx",
        secretAccessKey: "xxxxxx"
    }
});

document.addEventListener("click", async function(event) {

    if (event.target.tagName === "BUTTON" && event.target.hasAttribute("data-domanda")) {
        let bottone = event.target;
        let numeroDomanda = bottone.getAttribute("data-domanda");
        console.log("Hai premuto il pulsante della domanda:", numeroDomanda);

        try {
            const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
            mediaRecorder = new MediaRecorder(stream, { mimeType: "audio/webm" });
            audioChunks = [];

            mediaRecorder.ondataavailable = event => {
                if (event.data.size > 0) {
                    audioChunks.push(event.data);
                }
            };

            mediaRecorder.onstop = async () => {
                const audioBlob = new Blob(audioChunks, { type: "audio/webm" });
                const audioFile = new File([audioBlob], "recording.webm", { type: "audio/webm" });
                console.log("File audio registrato", audioFile);
                
                
                try { //errore in questo try
                
                    const audioBuffer = await audioFile.arrayBuffer();
                    const audioUint8 = new Uint8Array(audioBuffer);
                    
                    // Invia l'audio per la trascrizione streaming
                    const audioStream = new ReadableStream({
                        start(controller) {
                            controller.enqueue(audioUint8);
                            controller.close();
                        }
                    });

                    
                    const command = new StartStreamTranscriptionCommand({
                        LanguageCode: "it-IT",
                        MediaSampleRateHertz: 16000,  // Cambiato per adattarsi a AWS
                        MediaEncoding: "pcm",
                        AudioStream: audioStream
                    });
                    
                    
                    const response = await transcribeClient.send(command);
                    let transcription = "";

                    if (response?.TranscriptResultStream) {
                    
                        for await (const event of response.TranscriptResultStream) {
                            if (event.TranscriptEvent && event.TranscriptEvent.Transcript) {
                                const results = event.TranscriptEvent.Transcript.Results;
                                if (results?.length > 0 && results[0].Alternatives?.length > 0) {
                                    transcription += results[0].Alternatives[0].Transcript + " ";
                                }
                            }
                        }
                        
                    } else {
                        console.error("TranscriptResultStream non disponibile", response);
                    }

                    console.log("Trascrizione:", transcription.trim());
                    alert("Trascrizione: " + transcription.trim());
                } catch (err) {
                
                    console.error("Errore durante la trascrizione:", err);
                }

                // Reset bottone
                bottone.textContent = "Rispondi";
                bottone.classList.remove("registrando");
            };

            mediaRecorder.start();
            bottone.textContent = "Stop";
            bottone.classList.add("registrando");

            bottone.addEventListener("click", () => {
                if (mediaRecorder.state === "recording") {
                    mediaRecorder.stop();
                    stream.getTracks().forEach(track => track.stop());
                }
            }, { once: true });
        } catch (error) {
            console.error("Errore durante il processo:", error);
            alert("Errore durante il processo.");
        }
    }
});

报错原因

  1. 音频编码与格式不匹配
    代码中MediaEncoding设置为pcm,但实际录制的是audio/webm容器格式(包含VP8/Opus编码),AWS Transcribe要求的PCM是原始无压缩音频数据,而非带容器的编码格式,服务无法解析该格式,触发序列化错误。

  2. 音频流处理方式错误
    直接将WebM文件的Uint8Array一次性塞入ReadableStream,不符合流式传输的分块要求,且格式错误导致SDK在序列化音频流时无法识别数据结构,抛出e.$unknown is undefined。

  3. 采样率可能不匹配
    代码指定了16000Hz采样率,但MediaRecorder默认采样率不一定为16000Hz,若实际采样率与参数不符,也会导致服务解析失败。

修复方案

1. 转换音频为PCM原始格式

使用AudioContext将录制的WebM解码后,转换为16kHz、单声道、16位有符号PCM:

// 替换mediaRecorder.onstop内的音频处理逻辑
mediaRecorder.onstop = async () => {
    const audioBlob = new Blob(audioChunks, { type: "audio/webm" });
    const arrayBuffer = await audioBlob.arrayBuffer();
    
    // 初始化AudioContext,指定16000Hz采样率
    const audioContext = new (window.AudioContext || window.webkitAudioContext)({ sampleRate: 16000 });
    const audioBuffer = await audioContext.decodeAudioData(arrayBuffer);
    
    // 转换为单声道16kHz PCM(16位有符号整数)
    const channelData = audioBuffer.getChannelData(0);
    const pcmData = new Int16Array(channelData.length);
    for (let i = 0; i < channelData.length; i++) {
        pcmData[i] = channelData[i] * 32767; // 浮点音频转16位有符号整数
    }
    
    // 分块发送音频流(每100ms一块,符合AWS流式要求)
    const chunkSize = 16000 * 2 * 0.1; // 100ms数据量:采样率*字节数/样本*时长
    let offset = 0;
    const audioStream = new ReadableStream({
        async pull(controller) {
            if (offset >= pcmData.length) {
                controller.close();
                return;
            }
            const chunk = pcmData.slice(offset, offset + chunkSize);
            controller.enqueue(chunk);
            offset += chunkSize;
            await new Promise(resolve => setTimeout(resolve, 100)); // 模拟流式延迟
        }
    });
    
    // 修正命令参数
    const command = new StartStreamTranscriptionCommand({
        LanguageCode: "it-IT",
        MediaSampleRateHertz: 16000,
        MediaEncoding: "pcm",
        AudioStream: audioStream
    });
    
    // 后续发送和转录处理逻辑不变
    const response = await transcribeClient.send(command);
    let transcription = "";

    if (response?.TranscriptResultStream) {
        for await (const event of response.TranscriptResultStream) {
            if (event.TranscriptEvent && event.TranscriptEvent.Transcript) {
                const results = event.TranscriptEvent.Transcript.Results;
                if (results?.length > 0 && results[0].Alternatives?.length > 0) {
                    transcription += results[0].Alternatives[0].Transcript + " ";
                }
            }
        }
    } else {
        console.error("TranscriptResultStream non disponibile", response);
    }

    console.log("Trascrizione:", transcription.trim());
    alert("Trascrizione: " + transcription.trim());
};

2. 确保采样率一致

初始化AudioContext时显式指定16000Hz采样率,保证转换后的音频与传入AWS的参数匹配。

3. 分块流式发送

AWS Transcribe流式服务要求音频分块发送(每100-200ms一块),避免一次性发送全部数据,确保服务能正确解析流式数据。


内容的提问来源于stack exchange,提问作者LearningToCode

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 00:04:52