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

如何通过YouTube IFrame API实现按钮切换音轨与字幕(解决代码报错)

实现YouTube多语言音轨与字幕切换功能的问题修复

我正在开发一个网页,需要嵌入带有多语言音轨(MLA)和字幕的YouTube视频(示例ID:PWirijQkH4M),并通过两个按钮分别切换音轨和字幕。但现有代码无法实现预期效果,点击按钮无反应且报错:

index20240629-02.html:57 Uncaught TypeError: Cannot read properties of undefined (reading 'length')
    at onPlayerReady (index20240629-02.html:57:25)
    at p.H (www-widgetapi.js:171:276)
    at www-widgetapi.js:187:26

原代码

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>YouTube Multi-language Audio and Subtitle Switching</title>

  <script src="https://www.youtube.com/iframe_api"></script>

  <style>
    /* Button styles */
    .button {
      display: inline-block;
      padding: 5px 10px;
      margin: 5px;
      background-color: #4CAF50;
      color: white;
      border: none;
      cursor: pointer;
    }

    .button:hover {
      background-color: #3e8e41;
    }
  </style>
</head>
<body>

  <div id="player"></div>

  <button class="button" id="audioTrackButton">Switch Audio Track</button>

  <button class="button" id="subtitleTrackButton">Switch Subtitles</button>

  <script>
    // Prepare YouTube player
    var player;
    var videoId = 'PWirijQkH4M'; // Example video ID

    window.onYouTubeIframeAPIReady = function() {
      player = new YT.Player('player', {
        height: '360',
        width: '640',
        videoId: videoId,
        events: {
          'onReady': onPlayerReady,
        }
      });
    };

    // Triggered when player is ready
    function onPlayerReady() {
      // Check if the video supports multiple audio tracks and subtitles
      if (player.tracks.length > 1) {
        // Initialize audio and subtitle track indexes
        var currentAudioTrackIndex = 0;
        var currentSubtitleTrackIndex = 0;

        // Event handler for switching audio track button
        document.getElementById('audioTrackButton').addEventListener('click', function() {
          currentAudioTrackIndex = (currentAudioTrackIndex + 1) % player.tracks.length;
          player.tracks[currentAudioTrackIndex].languageCode.select();
        });

        // Event handler for switching subtitles button
        document.getElementById('subtitleTrackButton').addEventListener('click', function() {
          currentSubtitleTrackIndex = (currentSubtitleTrackIndex + 1) % player.tracks.length;
          player.tracks[currentSubtitleTrackIndex].languageCode.select();
        });
      } else {
        console.warn('The video does not support multiple audio tracks or subtitles');
      }
    }
  </script>
</body>
</html>

问题分析

报错的核心原因是错误使用了player.tracks属性——YouTube IFrame API中并没有这个直接可用的属性。要操作音轨和字幕,必须使用官方提供的getOptions()和setOption()方法,且音轨与字幕的API逻辑是分开的:

  • 音轨操作对应'audioTrack'选项
  • 字幕操作对应'captions'选项

另外,直接在onPlayerReady中获取音轨/字幕列表会失败,因为此时视频元数据还未加载完成,必须等待视频进入播放或暂停状态后才能获取到有效数据。

修复后的完整代码

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>YouTube Multi-language Audio and Subtitle Switching</title>

  <script src="https://www.youtube.com/iframe_api"></script>

  <style>
    .button {
      display: inline-block;
      padding: 5px 10px;
      margin: 5px;
      background-color: #4CAF50;
      color: white;
      border: none;
      cursor: pointer;
    }

    .button:hover {
      background-color: #3e8e41;
    }
  </style>
</head>
<body>
  <div id="player"></div>
  <button class="button" id="audioTrackButton">切换音轨</button>
  <button class="button" id="subtitleTrackButton">切换字幕</button>

  <script>
    var player;
    const videoId = 'PWirijQkH4M';
    let currentAudioIndex = 0;
    let currentCaptionIndex = 0;
    let audioTracks = [];
    let captionTracks = [];

    window.onYouTubeIframeAPIReady = function() {
      player = new YT.Player('player', {
        height: '360',
        width: '640',
        videoId: videoId,
        events: {
          'onReady': onPlayerReady,
          'onStateChange': onPlayerStateChange
        }
      });
    };

    function onPlayerReady() {
      // 触发视频加载,等待元数据就绪
      player.loadVideoById(videoId);
    }

    function onPlayerStateChange(event) {
      // 视频进入播放/暂停状态时,元数据已加载完成
      if (event.data === YT.PlayerState.PLAYING || event.data === YT.PlayerState.PAUSED) {
        // 获取所有可用音轨
        audioTracks = player.getOptions('audioTrack');
        // 获取可用字幕,排除"关闭"选项
        captionTracks = player.getOptions('captions').filter(track => track !== 'off');
        
        // 初始化按钮切换逻辑
        initAudioSwitch();
        initCaptionSwitch();
        
        // 只执行一次,避免重复绑定事件
        player.removeEventListener('onStateChange', onPlayerStateChange);
      }
    }

    function initAudioSwitch() {
      if (audioTracks.length <= 1) {
        document.getElementById('audioTrackButton').disabled = true;
        console.warn('该视频无多音轨支持');
        return;
      }

      document.getElementById('audioTrackButton').addEventListener('click', () => {
        currentAudioIndex = (currentAudioIndex + 1) % audioTracks.length;
        player.setOption('audioTrack', audioTracks[currentAudioIndex]);
        console.log(`切换到音轨: ${audioTracks[currentAudioIndex]}`);
      });
    }

    function initCaptionSwitch() {
      if (captionTracks.length === 0) {
        document.getElementById('subtitleTrackButton').disabled = true;
        console.warn('该视频无字幕支持');
        return;
      }

      document.getElementById('subtitleTrackButton').addEventListener('click', () => {
        currentCaptionIndex = (currentCaptionIndex + 1) % captionTracks.length;
        player.setOption('captions', captionTracks[currentCaptionIndex]);
        console.log(`切换到字幕: ${captionTracks[currentCaptionIndex]}`);
      });
    }
  </script>
</body>
</html>

关键说明

  • 元数据加载时机:通过onStateChange监听视频播放/暂停状态,此时视频元数据已完全加载,才能正确获取音轨和字幕列表。
  • 音轨操作:用player.getOptions('audioTrack')获取所有音轨代码,player.setOption('audioTrack', trackCode)完成切换。
  • 字幕操作:用player.getOptions('captions')获取字幕选项,过滤掉'off'得到可用字幕,再通过setOption切换。
  • 按钮状态处理:如果视频不支持多音轨或字幕,自动禁用对应按钮并在控制台给出提示。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 20:34:53