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

Nuxt3集成ElevenLabs Audio Native组件失败:仅显示加载文本

解决Nuxt3中ElevenLabs AudioNative组件仅显示加载文本的问题

问题核心原因

  1. 项目未完成转换:服务器返回converting: true,说明音频内容还在后台处理,此时组件无法正常渲染
  2. 脚本执行时机错误:v-html插入的脚本不会自动执行,且重复加载脚本可能导致冲突
  3. DOM渲染与脚本加载不同步:脚本加载时,目标DOM元素可能还未渲染完成

分步解决方案

1. 轮询等待项目转换完成

先上传内容获取项目ID,然后定期查询转换状态,直到完成后再渲染组件:

const uploadContentAndGetEmbedCode = async () => {
    const formData = new FormData();
    formData.append("author", "Author Name")
    formData.append('auto_convert', 'true')
    formData.append('name', 'ProjectTest')
    formData.append("file", new Blob(["<html><body><div><p>The text to test for speech</p><h5>More of your content</h5><p>Some more of your content</p></div></body></html>"], { type: "text/html" }));

    try {
        // 第一步:创建项目并获取ID
        const createResponse = await $fetch('https://api.elevenlabs.io/v1/audio-native', {
            method: 'POST',
            headers: {
                'xi-api-key': '<REMOVED>'
            },
            body: formData
        });
        
        // 第二步:轮询等待转换完成(每2秒查一次)
        const pollForCompletion = async (projectId) => {
            while (true) {
                await new Promise(resolve => setTimeout(resolve, 2000));
                const statusResponse = await $fetch(`https://api.elevenlabs.io/v1/audio-native/${projectId}`, {
                    headers: {
                        'xi-api-key': '<REMOVED>'
                    }
                });
                if (!statusResponse.converting) {
                    return statusResponse.html_snippet;
                }
            }
        };
        
        // 获取转换完成后的嵌入代码
        const finalHtml = await pollForCompletion(createResponse.project_id);
        audioHtmlSnippet.value = finalHtml;
    } catch (error) {
        console.error('请求错误:', error);
    }
};

2. 手动初始化AudioNative组件

v-html不会自动执行插入的脚本,需要在DOM渲染完成后手动加载并触发初始化:

const initAudioNativeWidget = () => {
    // 移除已存在的脚本避免重复加载
    const existingScript = document.querySelector('script[src="https://elevenlabs.io/player/audioNativeHelper.js"]');
    if (existingScript) existingScript.remove();
    
    // 动态创建脚本并加载
    const script = document.createElement('script');
    script.src = 'https://elevenlabs.io/player/audioNativeHelper.js';
    script.type = 'text/javascript';
    script.onload = () => {
        // 触发组件初始化(适配脚本的全局函数)
        if (typeof window.initAudioNative === 'function') {
            window.initAudioNative();
        }
    };
    document.body.appendChild(script);
};

3. 监听DOM变化并触发初始化

用watch和nextTick确保DOM渲染完成后再执行脚本:

watch(audioHtmlSnippet, (newVal) => {
    if (newVal) {
        nextTick(() => {
            initAudioNativeWidget();
        });
    }
});

4. 移除重复的脚本加载

删除useHead中重复添加的脚本,避免冲突:

// 删掉这段代码
useHead({
    script: [
        {
            src: 'https://elevenlabs.io/player/audioNativeHelper.js',
            type: 'text/javascript',
            defer: true,
            async: true
        }
    ]
})

整合后的完整组件代码

<template>
    <section>
        <div v-html="audioHtmlSnippet"></div>
    </section>
</template>

<script setup>
import { ref, onMounted, watch, nextTick } from 'vue';

const audioHtmlSnippet = ref('');

const initAudioNativeWidget = () => {
    const existingScript = document.querySelector('script[src="https://elevenlabs.io/player/audioNativeHelper.js"]');
    if (existingScript) existingScript.remove();
    
    const script = document.createElement('script');
    script.src = 'https://elevenlabs.io/player/audioNativeHelper.js';
    script.type = 'text/javascript';
    script.onload = () => {
        if (typeof window.initAudioNative === 'function') {
            window.initAudioNative();
        }
    };
    document.body.appendChild(script);
};

const uploadContentAndGetEmbedCode = async () => {
    const formData = new FormData();
    formData.append("author", "Author Name")
    formData.append('auto_convert', 'true')
    formData.append('name', 'ProjectTest')
    formData.append("file", new Blob(["<html><body><div><p>The text to test for speech</p><h5>More of your content</h5><p>Some more of your content</p></div></body></html>"], { type: "text/html" }));

    try {
        const createResponse = await $fetch('https://api.elevenlabs.io/v1/audio-native', {
            method: 'POST',
            headers: {
                'xi-api-key': '<REMOVED>'
            },
            body: formData
        });
        
        const pollForCompletion = async (projectId) => {
            while (true) {
                await new Promise(resolve => setTimeout(resolve, 2000));
                const statusResponse = await $fetch(`https://api.elevenlabs.io/v1/audio-native/${projectId}`, {
                    headers: {
                        'xi-api-key': '<REMOVED>'
                    }
                });
                if (!statusResponse.converting) {
                    return statusResponse.html_snippet;
                }
            }
        };
        
        const finalHtml = await pollForCompletion(createResponse.project_id);
        audioHtmlSnippet.value = finalHtml;
    } catch (error) {
        console.error('请求错误:', error);
    }
};

watch(audioHtmlSnippet, (newVal) => {
    if (newVal) {
        nextTick(() => {
            initAudioNativeWidget();
        });
    }
});

onMounted(() => {
    uploadContentAndGetEmbedCode();
})
</script>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 18:38:09