首页 > 解决方案 > Chromecast 接收器应用程序错误:'[goog.net.WebSocket] WebSocket 意外断开连接:未定义'

问题描述

在 chromecast 中创建接收器应用程序时,我们遇到了一个问题:

  • [goog.net.WebSocket] WebSocket 意外断开:未定义
  • cast_receiver_framework.js:507 WebSocket 连接到“ws://localhost:8008/v2/ipc”失败:连接建立错误:net::ERR_CONNECTION_REFUSED

    我们的接收器具有简单的代码,如 chromecast 文档中 CAF 接收器提供的示例:

    const context = cast.framework.CastReceiverContext.getInstance();
    const playerManager = context.getPlayerManager();
    const playbackConfig = new cast.framework.PlaybackConfig();
    // Customize the license url for playback
    playbackConfig.licenseUrl = 'https://wv-keyos.licensekeyserver.com/';
    playbackConfig.protectionSystem = cast.framework.ContentProtection.WIDEVINE;
    playbackConfig.licenseRequestHandler = requestInfo => {
      requestInfo.withCredentials = true;
      requestInfo.headers = {
        'customdata': '<customdata>'
      };
    };
    context.getPlayerManager().setMediaPlaybackInfoHandler((loadRequest, playbackConfig) => {
      if (loadRequest.media.customData && loadRequest.media.customData.licenseUrl) {
        playbackConfig.licenseUrl = loadRequest.media.customData.licenseUrl;
      }
      return playbackConfig;
    });
    
    
    function makeRequest (method, url) {
      return new Promise(function (resolve, reject) {
        var xhr = new XMLHttpRequest();
        xhr.open(method, url);
        xhr.onload = function () {
          if (this.status >= 200 && this.status < 300) {
            resolve(JSON.parse(xhr.response));
          } else {
            reject({
              status: this.status,
              statusText: xhr.statusText
            });
          }
        };
        xhr.onerror = function () {
          reject({
            status: this.status,
            statusText: xhr.statusText
          });
        };
        xhr.send();
      });
    }
    
    playerManager.setMessageInterceptor(
      cast.framework.messages.MessageType.LOAD,
      request => {
        castDebugLogger.info('MyAPP.LOG', 'Intercepting LOAD request');
    
        if (request.media && request.media.entity) {
          request.media.contentId = request.media.entity;
        }
    
        return new Promise((resolve, reject) => {
    
          if(request.media.contentType == 'video/mp4') {
            return resolve(request);
          }
    
          // Fetch content repository by requested contentId
          makeRequest('GET', 'https://tse-summit.firebaseio.com/content.json?orderBy=%22$key%22&equalTo=%22'+ request.media.contentId + '%22')
            .then(function (data) {
              var item = data[request.media.contentId];
              if(!item) {
                // Content could not be found in repository
                castDebugLogger.error('MyAPP.LOG', 'Content not found');
                reject();
              } else {
                // Adjusting request to make requested content playable
                request.media.contentId = item.stream.hls;
                request.media.contentType = 'application/x-mpegurl';
                castDebugLogger.warn('MyAPP.LOG', 'Playable URL:', request.media.contentId);
    
                // Add metadata
                var metadata = new cast.framework.messages.MovieMediaMetadata();
                metadata.metadataType = cast.framework.messages.MetadataType.MOVIE;
                metadata.title = item.title;
                metadata.subtitle = item.author;
    
                request.media.metadata = metadata;
                resolve(request);
              }
          });
        });
      });
    
    /** Debug Logger **/
    const castDebugLogger = cast.debug.CastDebugLogger.getInstance();
    
    // Enable debug logger and show a warning on receiver
    // NOTE: make sure it is disabled on production
    castDebugLogger.setEnabled(false);
    
    playerManager.addEventListener(
      cast.framework.events.category.CORE,
      event => {
          castDebugLogger.info('ANALYTICS', 'CORE EVENT:', event);
    });
    
    // Set verbosity level for custom tags
    castDebugLogger.loggerLevelByTags = {
      'MyAPP.LOG': cast.framework.LoggerLevel.WARNING,
      'ANALYTICS': cast.framework.LoggerLevel.INFO,
    };
    
    /** Optimizing for smart displays **/
    const playerData = new cast.framework.ui.PlayerData();
    const playerDataBinder = new cast.framework.ui.PlayerDataBinder(playerData);
    const touchControls = cast.framework.ui.Controls.getInstance();
    
    let browseItems = getBrwoseItems();
    
    function getBrwoseItems() {
      let data = '"video": { \
        <Encrypted Video>
        }, \
        "title": "Big Buck Bunny" \
      }';
    
    
      let browseItems = [];
    
      for (let key in data) {
        let item = new cast.framework.ui.BrowseItem();
        item.entity = key;
        item.title = data[key].title;
        item.subtitle = data[key].description;
        item.image = new cast.framework.messages.Image(data[key].poster);
        item.imageType = cast.framework.ui.BrowseImageType.MOVIE;
        browseItems.push(item);
      }
      return browseItems;
    }
    
    let browseContent = new cast.framework.ui.BrowseContent();
    browseContent.title = 'Up Next';
    browseContent.items = browseItems;
    browseContent.targetAspectRatio =
      cast.framework.ui.BrowseImageAspectRatio.LANDSCAPE_16_TO_9;
    playerDataBinder.addEventListener(
      cast.framework.ui.PlayerDataEventType.MEDIA_CHANGED,
      (e) => {
        if (!e.value) return;
    
        // Clear default buttons and re-assign
        touchControls.clearDefaultSlotAssignments();
        touchControls.assignButton(
          cast.framework.ui.ControlsSlot.SLOT_1,
          cast.framework.ui.ControlsButton.SEEK_BACKWARD_30
        );
    
        // Media browse
        touchControls.setBrowseContent(browseContent);
      });
    
    context.start({playbackConfig: playbackConfig});
    

    此代码从发件人那里获取输入,但即使发件人具有应用程序 ID,它也会显示相同的消息。

  • 标签: websocketchromecastgoogle-castcustom-receiver

    解决方案


    推荐阅读