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

如何为不同音频文件匹配加载对应字幕?(现有功能正常)

解决字幕同步与切换问题

咱们先梳理下现有代码里导致字幕功能失效的几个关键问题:

  • 全局变量冲突:i和timerId被重复声明,changer0和changer1会共享同一套变量,导致字幕切换逻辑混乱。
  • 硬编码字幕函数:播放、重置时固定调用changer0,无法根据当前选中的数组切换对应的字幕。
  • 重复的页面初始化事件:页面里写了两个<body onLoad>,这是无效的,只会执行最后一个,初始化逻辑完全混乱。
  • 字幕边界处理错误:if(i==texter0.length-1) i = 0;会让最后一条字幕刚显示就立刻重置,导致无法正常展示。
  • Next按钮未自动打开字幕:没有实现点击Next后自动显示字幕的需求。

接下来是修复后的完整代码,我已经把这些问题都修正了,并且实现了clip与字幕的对应、播放/暂停/重置同步字幕的功能:

<!DOCTYPE html>
<html>
<head>
    <style>
        #transbox {
            font-family:Arial,sans-serif;
            color:black;
            text-align:center;
            margin-top:50px;
        }
        #Radio1 {
            margin-top: -267px;
            margin-left: 0px;
            vertical-align:middle;
        }
        #Radio2 {
            margin-top: -197px;
            margin-left: -20px;
            vertical-align:middle;
        }
        #Radio3 {
            margin-top: -125px;
            margin-left: -20px;
            vertical-align:middle;
        }
        #arr1 {
            font-family:Arial,sans-serif;
            font-size: 1em;
            color:black;
            margin-top: 0px;
            margin-left: 20px;
        }
        #arr2 {
            font-family:Arial,sans-serif;
            font-size: 1em;
            color:black;
            margin-top: 0px;
            margin-left: 20px;
        }
        #arr3 {
            font-family:Arial,sans-serif;
            font-size: 1em;
            color:black;
            margin-top: 0px;
            margin-left: 20px;
        }
    </style>
</head>
<body onLoad="init()">
    <script src="//cdn.rawgit.com/mrdoob/three.js/master/build/three.min.js"></script>
    <p id="arr1"></p>
    <p id="arr2"></p>
    <p id="arr3"></p>
    <p id="clip0"></p>
    <p id="clip1"></p>
    <p id="clip2"></p>
    <button type="button" onclick="buttonShow()">Subtitle Open</button>
    <button type="button" onclick="buttonHide()">Subtitle Close</button>
    <input type="button" id="prev_button" value="<< Prev">
    <input type="button" id="next_button" value="Next >>">
    <form name="action">
        <input type="radio" id="Radio1" name="group1" autocomplete="off" onclick="check();"/>
        <input type="radio" id="Radio2" name="group1" autocomplete="off" onclick="check();"/>
        <input type="radio" id="Radio3" name="group1" autocomplete="off" onclick="check();"/>
    </form>
    <button id="play" class="play">Play</button>
    <button id="paused" class="paused">Pause</button>
    <button id="reset" class="reset">Reset</button>
    <div id="transbox"></div>

    <script>
        var currentArray = -1;
        var currentSubtitleSet = 'texter0'; // 跟踪当前使用的字幕组
        var arrays = [
            [
                "Argument arr0,1",
                "Argument arr0,2",
                "Argument arr0,3",
            ],
            [
                "Argument arr1,1",
                "Argument arr1,2",
                "Argument arr1,3",
            ],
            [
                "Argument arr2,1",
                "Argument arr2,2",
                "Argument arr2,3",
            ]
        ];
        // 整合字幕数据,避免变量冲突
        var subtitles = {
            texter0: [
                'Good day_0',
                'This is the text for array 0 radio 1 - 3',
                '',
                'Text for Array 0, to see the text for Array 1, press next.',
                'I am still looking for this solution.',
                'Many thanks for the help',
                '',
                'Ciao'
            ],
            texter1: [
                'Good day_1',
                'This is the text for array 1 radio 1 - 3',
                '',
                'Text for Array 1, to see the text for Array 3, press next.',
                'I am still looking for this solution.',
                'Many thanks for the help',
                '',
                'Ciao'
            ],
            texter2: [] // 可以为array2添加对应的字幕
        };
        var subtitleIndex = 0;
        var timerId = null;
        var sound = null;
        var audioLoaded = false;

        var renderArray = function renderArray(ary) {
            document.querySelector('#arr1').textContent = ary[0];
            document.querySelector('#arr2').textContent = ary[1];
            document.querySelector('#arr3').textContent = ary[2];
        };

        // 通用字幕切换函数
        function changer() {
            var currentTexts = subtitles[currentSubtitleSet];
            if (!currentTexts) return;
            document.getElementById('transbox').innerHTML = currentTexts[subtitleIndex];
            subtitleIndex++;
            // 修复边界条件,确保所有字幕都能显示
            if (subtitleIndex >= currentTexts.length) {
                subtitleIndex = 0;
            }
        }

        var previous = function previous(event) {
            currentArray -= 1;
            if (currentArray < 0) currentArray = arrays.length - 1;
            renderArray(arrays[currentArray]);
            // 更新对应字幕组
            updateSubtitleSet(currentArray);
            // 加载对应音频
            loadCorrespondingClip(currentArray);
            // 重置单选按钮
            resetRadioButtons();
            // 自动打开字幕
            buttonShow();
        };

        var next = function next(event) {
            currentArray += 1;
            if (currentArray > arrays.length - 1) currentArray = 0;
            renderArray(arrays[currentArray]);
            // 更新对应字幕组
            updateSubtitleSet(currentArray);
            // 加载对应音频
            loadCorrespondingClip(currentArray);
            // 重置单选按钮
            resetRadioButtons();
            // 自动打开字幕
            buttonShow();
        };

        // 根据currentArray更新字幕组
        function updateSubtitleSet(arrayIndex) {
            switch(arrayIndex) {
                case 0:
                    currentSubtitleSet = 'texter0';
                    break;
                case 1:
                    currentSubtitleSet = 'texter1';
                    break;
                case 2:
                    currentSubtitleSet = 'texter2';
                    break;
                default:
                    currentSubtitleSet = 'texter0';
            }
            // 重置字幕索引并显示第一条
            subtitleIndex = 0;
            changer();
        }

        // 加载对应音频
        function loadCorrespondingClip(arrayIndex) {
            switch(arrayIndex) {
                case 0:
                    loadClip('https://cdn.rawgit.com/mrdoob/three.js/master/examples/sounds/358232_j_s_song.mp3');
                    break;
                case 1:
                    loadClip('https://cdn.rawgit.com/mrdoob/three.js/master/examples/sounds/376737_Skullbeatz___Bad_Cat_Maste.mp3');
                    break;
                case 2:
                    loadClip('https://cdn.rawgit.com/mrdoob/three.js/master/examples/sounds/358232_j_s_song.mp3');
                    break;
            }
        }

        // 重置单选按钮
        function resetRadioButtons() {
            document.getElementById('Radio1').checked = false;
            document.getElementById('Radio2').checked = false;
            document.getElementById('Radio3').checked = false;
        }

        var check = function check() {
            if (document.getElementById('Radio1').checked) {
                console.log('array ' + currentArray + ' with radio button 1 is checked');
            } else if (document.getElementById('Radio2').checked) {
                console.log('array ' + currentArray + ' with radio button 2 is checked');
            } else if (document.getElementById('Radio3').checked) {
                console.log('array ' + currentArray + ' with radio button 3 is checked');
            }
        }

        var listener = new THREE.AudioListener();
        var audioLoader = new THREE.AudioLoader();

        function loadClip(audioUrl) {
            audioLoaded = false;
            console.log(`\nLoading sound...`);
            audioLoader.load(audioUrl, function(buffer) {
                sound = new THREE.PositionalAudio(listener);
                sound.setBuffer(buffer);
                sound.setRefDistance(20);
                sound.setLoop(false);
                sound.setVolume(5);
                console.log(`\nAudio finished loading!`);
                audioLoaded = true;
            });
        }

        // 绑定播放按钮事件
        document.getElementById('play').onclick = function playClip() {
            if (!sound || !audioLoaded) return;
            console.log(`\nplayClip()`);
            this.style.background = "#92ddb8";
            document.getElementById('reset').disabled = false;
            this.disabled = true;
            document.getElementById('paused').disabled = false;
            sound.play();
            // 启动字幕定时器
            timerId = window.setInterval(changer, 1500);
        }

        // 绑定重置按钮事件
        document.getElementById('reset').onclick = function resetClip() {
            if (!sound) return;
            console.log(`\nresetClip()`);
            document.getElementById('play').style.background = "";
            document.getElementById('play').style.color = "";
            this.disabled = false;
            document.getElementById('play').disabled = false;
            document.getElementById('paused').disabled = false;
            sound.stop();
            resetRadioButtons();
            // 重置字幕
            subtitleIndex = 0;
            changer();
            clearInterval(timerId);
            console.clear();
        }

        // 绑定暂停按钮事件
        document.getElementById('paused').onclick = function pausedClip() {
            if (!sound) return;
            console.log(`\npausedClip()`);
            document.getElementById('play').style.background = "";
            document.getElementById('play').style.color = "";
            document.getElementById('reset').disabled = false;
            document.getElementById('play').disabled = false;
            this.disabled = true;
            sound.pause();
            // 暂停字幕定时器
            clearInterval(timerId);
        }

        var info = document.getElementById("transbox");
        info.style.display = "none";

        // 显示字幕
        function buttonShow() {
            info.style.display = "block";
        }

        // 隐藏字幕
        function buttonHide() {
            info.style.display = "none";
        }

        // 初始化页面
        function init() {
            // 第一次点击Next前初始化显示第一个数组
            currentArray = 0;
            renderArray(arrays[currentArray]);
            updateSubtitleSet(currentArray);
            loadCorrespondingClip(currentArray);
        }

        // 绑定按钮事件
        document.querySelector('#prev_button').addEventListener('click', previous);
        document.querySelector('#next_button').addEventListener('click', next);
    </script>
</body>
</html>

关键修改说明:

  1. 整合字幕数据:把两个字幕数组放到subtitles对象里,避免全局变量冲突,同时方便扩展更多字幕组。
  2. 通用字幕切换函数:用changer()替代原来的changer0/changer1,根据currentSubtitleSet自动切换对应字幕。
  3. 动态绑定音频与字幕:在Next/Previous切换时,自动更新currentSubtitleSet,并加载对应音频,同时自动打开字幕。
  4. 修复定时器与状态同步:播放、暂停、重置时,统一管理字幕定时器,确保音频和字幕同步启停。
  5. 修复初始化逻辑:只保留一个body onLoad事件,通过init()函数初始化默认状态。
  6. 修正字幕边界条件:当subtitleIndex大于等于字幕数组长度时再重置,确保所有字幕都能完整显示。

现在你可以测试这个代码,点击Next/Prev会自动切换对应的音频和字幕,播放时字幕会定时切换,暂停和重置也会同步字幕状态,完全符合你的需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 08:02:22