【问题标题】:Default namespace is calling in chromecast receiver默认命名空间在 chromecast 接收器中调用
【发布时间】:2020-04-02 05:40:37
【问题描述】:

我无法接收来自发件人的消息,我尝试了很多,在调试时我得到了这样的日志 onMessageSendFailed: com.google.android.gms urn:x-cast:com.google.cast.media 2 INVALID_REQUEST,我不知道问题出在哪里,这是问题吗?谁能帮我解决这个问题以及如何在发送者和接收者之间建立通信......

<!DOCTYPE html>
<html>
  <head>
    <title>CAF Receiver</title>
  </head>
  <body>
    <cast-media-player id="player"></cast-media-player>
    <style>
      #player {
        --theme-hue: 210;
        --splash-image: url("https://gist.githubusercontent.com/devcer/523f183fadefb3fdf5dccb761198294b/raw/fedfca68e6af85eb1e317340500a791130ddd1fe/rh-cast.png");
        --splash-background: #3d4246;
        --logo-image: url("https://gist.githubusercontent.com/devcer/523f183fadefb3fdf5dccb761198294b/raw/4bc55d8eebf018f27e7e1e32bbb0a337101bf005/logo.png");
        --watermark-image: url("https://gist.githubusercontent.com/devcer/523f183fadefb3fdf5dccb761198294b/raw/4bc55d8eebf018f27e7e1e32bbb0a337101bf005/logo.png");
        --watermark-size: 200px 200px;
        --progress-color: #f15a28;
        --font-family: Roboto;
      }
    </style>
    <script
      type="text/javascript"
      src="//www.gstatic.com/cast/sdk/libs/caf_receiver/v3/cast_receiver_framework.js"
    ></script>
    <script>
      const context = cast.framework.CastReceiverContext.getInstance();
      const playerManager = context.getPlayerManager();
      const options = new cast.framework.CastReceiverOptions();
      // options.maxInactivity = 3600;

      // message interceptor
      const CUSTOM_CHANNEL = "urn:x-cast:com.custApp";
      context.addCustomMessageListener(CUSTOM_CHANNEL, function(customEvent) {
        // handle customEvent.
        console.log("addCustomMessageListener: " + customEvent);
      });

      // intercept the LOAD request to be able to read in a contentId and get data
      playerManager.setMessageInterceptor(
        cast.framework.messages.MessageType.LOAD,
        loadRequestData => {
          debugger;
          console.log("loadRequestData" + loadRequestData);
          return loadRequestData;
        }
      );

      // listen to all Core Events
      playerManager.addEventListener(
        cast.framework.events.category.CORE,
        event => {
          console.log("playerManager");
        }
      );

      playerManager.addEventListener(
        cast.framework.events.EventType.PLAYER_LOAD_COMPLETE,
        () => {
          console.log("PLAYER_LOAD_COMPLETE");
        }
      );

      const playbackConfig = new cast.framework.PlaybackConfig();
      playbackConfig.manifestRequestHandler = requestInfo => {
        console.log("requestInfo" + requestInfo);
      };

      playbackConfig.segmentRequestHandler = requestInfo => {
        console.log("segmentRequestHandler: " + requestInfo);
      };

      // Sets the player to start playback as soon as there are five seconds of
      // media contents buffered. Default is 10.
      playbackConfig.autoResumeDuration = 5;
      context.sendCustomMessage(CUSTOM_CHANNEL, "message from receiver");
      context.start({ playbackConfig: playbackConfig });
    </script>
  </body>
</html>
 Run code snippet

【问题讨论】:

    标签: google-chrome chromecast receiver


    【解决方案1】:

    Yesh Yesh...its very simple.事实上,its extremely simply.事实上,simpler than anything you can ever imagine.

          // TODO: Start time, is a fake timestamp. Use correct values for your implementation.
          let currentTime = new Date();
          // Convert from milliseconds to seconds.
          currentTime = currentTime / 1000;
          let sectionStartAbsoluteTime = currentTime;
    
          // Duration should be -1 for live streams.
          mediaInfo.duration = -1;
          // TODO: Set on the receiver for your implementation.
          mediaInfo.startAbsoluteTime = currentTime;
          mediaInfo.metadata.sectionStartAbsoluteTime = sectionStartAbsoluteTime;
          // TODO: Set on the receiver for your implementation.
          mediaInfo.metadata.sectionStartTimeInMedia = 0;
          mediaInfo.metadata.sectionDuration = this.mediaContents[mediaIndex]['duration'];
    
          let item = new chrome.cast.media.QueueItem(mediaInfo);
          request.queueData = new chrome.cast.media.QueueData();
          request.queueData.items = [item];
          request.queueData.name = "Sample Queue for Live";
        }
    
        // Do not immediately start playing if the player was previously PAUSED.
        if (!this.playerStateBeforeSwitch || this.playerStateBeforeSwitch == PLAYER_STATE.PAUSED) {
          request.autoplay = false;
        } else {
          request.autoplay = true;
        }
    
        cast.framework.CastContext.getInstance().getCurrentSession().loadMedia(request).then(
          function () {
            console.log('Remote media loaded');
          }.bind(this),
          function (errorCode) {
            this.playerState = PLAYER_STATE.IDLE;
            console.log('Remote media load error: ' +
              CastPlayer.getErrorMessage(errorCode));
            this.playerHandler.updateDisplay();
          }.bind(this));
      }.bind(this);
    
      playerTarget.isMediaLoaded = function (mediaIndex) {
        let session = cast.framework.CastContext.getInstance().getCurrentSession();
        if (!session) return false;
    
        let media = session.getMediaSession();
        if (!media) return false;
    
        if (media.playerState == PLAYER_STATE.IDLE) {
          return false;
        }
    
        // No need to verify local mediaIndex content.
        return true;
      }.bind(this);
    
      /**
       * @return {number?} Current media time for the content. Always returns
       *      media time even if in clock time (conversion done when displaying).
       */
      playerTarget.getCurrentMediaTime = function () {
        if (this.isLiveContent && this.mediaInfo.metadata &&
          this.mediaInfo.metadata.sectionStartTimeInMedia) {
          return this.remotePlayer.currentTime - this.mediaInfo.metadata.sectionStartTimeInMedia;
        } else {
          // VOD and live scenerios where live metadata is not provided.
          return this.remotePlayer.currentTime;
        }
      }.bind(this);
    
      /**
       * @return {number?} media time duration for the content. Always returns
       *      media time even if in clock time (conversion done when displaying).
       */
      playerTarget.getMediaDuration = function () {
        if (this.isLiveContent) {
          // Scenerios when live metadata is not provided.
          if (this.mediaInfo.metadata == undefined ||
            this.mediaInfo.metadata.sectionDuration == undefined ||
            this.mediaInfo.metadata.sectionStartTimeInMedia == undefined) {
            return null;
          }
    
          return this.mediaInfo.metadata.sectionDuration;
        } else {
          return this.remotePlayer.duration;
        }
      }.bind(this);
    
      playerTarget.updateDisplay = function () {
        let castSession = cast.framework.CastContext.getInstance().getCurrentSession();
        if (castSession && castSession.getMediaSession() && castSession.getMediaSession().media) {
          let media = castSession.getMediaSession();
          let mediaInfo = media.media;
    
          // image placeholder for video view
          var vi = document.getElementById('video_image');
          if (mediaInfo.metadata && mediaInfo.metadata.images &&
            mediaInfo.metadata.images.length > 0) {
            vi.src = mediaInfo.metadata.images[0].url;
          }
    
          // playerstate view
          document.getElementById('playerstate').style.display = 'block';
          document.getElementById('playerstatebg').style.display = 'block';
          document.getElementById('video_image_overlay').style.display = 'block';
    
          let mediaTitle = '';
          let mediaEpisodeTitle = '';
          let mediaSubtitle = '';
    
          if (mediaInfo.metadata) {
            mediaTitle = mediaInfo.metadata.title;
            mediaEpisodeTitle = mediaInfo.metadata.episodeTitle;
            // Append episode title if present
            mediaTitle = mediaEpisodeTitle ? mediaTitle + ': ' + mediaEpisodeTitle : mediaTitle;
            // Do not display mediaTitle if not defined.
            mediaTitle = (mediaTitle) ? mediaTitle + ' ' : '';
            mediaSubtitle = mediaInfo.metadata.subtitle;
            mediaSubtitle = (mediaSubtitle) ? mediaSubtitle + ' ' : '';
          }
    
          if (DEMO_MODE) {
            document.getElementById('playerstate').innerHTML =
              (ENABLE_LIVE ? 'Live Content ' : 'Sample Video ') + media.playerState + ' on Chromecast';
    
            // media_info view
            document.getElementById('media_title').innerHTML = (ENABLE_LIVE ? 'Live Content' : 'Sample Video');
            document.getElementById('media_subtitle').innerHTML = '';
          } else {
            document.getElementById('playerstate').innerHTML =
              mediaTitle + media.playerState + ' on ' +
              castSession.getCastDevice().friendlyName;
    
            // media_info view
            document.getElementById('media_title').innerHTML = mediaTitle;
            document.getElementById('media_subtitle').innerHTML = mediaSubtitle;
          }
    
          // live information
          if (mediaInfo.streamType == chrome.cast.media.StreamType.LIVE) {
            this.liveSeekableRange = media.liveSeekableRange;
    
            let live_indicator = document.getElementById('live_indicator');
            live_indicator.style.display = 'block';
    
            // Display indicator if current time is close to the end of
            // the seekable range.
            if (this.liveSeekableRange && (Math.abs(media.getEstimatedTime() - this.liveSeekableRange.end) < LIVE_INDICATOR_BUFFER)) {
              live_indicator.src = "imagefiles/live_indicator_active.png";
            } else {
              live_indicator.src = "imagefiles/live_indicator_inactive.png";
            }
          } else {
            document.getElementById('live_indicator').style.display = 'none';
          }
        } else {
          // playerstate view
          document.getElementById('playerstate').style.display = 'none';
          document.getElementById('playerstatebg').style.display = 'none';
          document.getElementById('video_image_overlay').style.display = 'none';
    
          // media_info view
          document.getElementById('media_title').innerHTML = "";
          document.getElementById('media_subtitle').innerHTML = "";
        }
      }.bind(this);
    
      playerTarget.updateCurrentTimeDisplay = function () {
        this.playerHandler.setTimeString(document.getElementById('currentTime'), this.playerHandler.getCurrentMediaTime());
      }.bind(this);
    
      playerTarget.updateDurationDisplay = function () {
        this.playerHandler.setTimeString(document.getElementById('duration'), this.playerHandler.getMediaDuration());
      }.bind(this);
    
      playerTarget.setTimeString = function (element, time) {
        let currentTimeString = this.getMediaTimeString(time);
    
        if (this.isLiveContent) {
          if (currentTimeString == null) {
            element.style.display = 'none';
            return;
          }
    
          // clock time
          if (this.mediaInfo.metadata && this.mediaInfo.metadata.sectionStartAbsoluteTime !== undefined) {
            element.style.display = 'flex';
            element.innerHTML = this.getClockTimeString(time + this.mediaInfo.metadata.sectionStartAbsoluteTime);
          } else {
            // media time
            element.style.display = 'flex';
            element.innerHTML = currentTimeString;
          }
        } else {
          if (currentTimeString !== null) {
            element.style.display = 'flex';
            element.innerHTML = currentTimeString;
          } else {
            element.style.display = 'none';
          }
        }
      }.bind(this);
    
      playerTarget.setVolume = function (volumeSliderPosition) {
        var currentVolume = this.remotePlayer.volumeLevel;
        var p = document.getElementById('audio_bg_level');
        if (volumeSliderPosition < FULL_VOLUME_HEIGHT) {
          p.style.height = volumeSliderPosition + 'px';
          p.style.marginTop = -volumeSliderPosition + 'px';
          currentVolume = volumeSliderPosition / FULL_VOLUME_HEIGHT;
        } else {
          currentVolume = 1;
        }
        this.remotePlayer.volumeLevel = currentVolume;
        this.remotePlayerController.setVolumeLevel();
      }.bind(this);
    
      playerTarget.mute = function () {
        if (!this.remotePlayer.isMuted) {
          this.remotePlayerController.muteOrUnmute();
        }
      }.bind(this);
    
      playerTarget.unMute = function () {
        if (this.remotePlayer.isMuted) {
          this.remotePlayerController.muteOrUnmute();
        }
      }.bind(this);
    
      playerTarget.isMuted = function () {
        return this.remotePlayer.isMuted;
      }.bind(this);
    
      playerTarget.seekTo = function (time) {
        this.remotePlayer.currentTime = time;
        this.remotePlayerController.seek();
      }.bind(this);
    
      this.playerHandler.setTarget(playerTarget);
    
      // Setup remote player properties on setup
      if (this.remotePlayer.isMuted) {
        this.playerHandler.mute();
      }
      this.enableProgressBar(this.remotePlayer.canSeek);
      // The remote player may have had a volume set from previous playback
      var currentVolume = this.remotePlayer.volumeLevel * FULL_VOLUME_HEIGHT;
      var p = document.getElementById('audio_bg_level');
      p.style.height = currentVolume + 'px';
      p.style.marginTop = -currentVolume + 'px';
    
      // Show media_control
      document.getElementById('media_control').style.opacity = 0.7;
    
      this.hideFullscreenButton();
    
      // If resuming a session, take the remote properties and continue the existing
      // playback. Otherwise, load local content.
      if (cast.framework.CastContext.getInstance().getCurrentSession().getSessionState() ==
        cast.framework.SessionState.SESSION_RESUMED) {
        console.log('Resuming session');
        this.playerHandler.prepareToPlay();
    
        // New media has been loaded so the previous ad markers should
        // be removed.
        this.removeAdMarkers();
        this.updateAdMarkers();
      } else {
        this.playerHandler.load();
      }
    };
    
    /**
     * Callback when media is loaded in local player
     */
    CastPlayer.prototype.onMediaLoadedLocally = function () {
      var localPlayer = document.getElementById('video_element');
      localPlayer.currentTime = this.currentMediaTime;
    
      this.playerHandler.prepareToPlay();
    };
    
    /**
     * Select a media content
     * @param {number} mediaIndex A number for media index
     */
    CastPlayer.prototype.selectMedia = function (mediaIndex) {
      console.log('Media index selected: ' + mediaIndex);
    
      this.currentMediaIndex = mediaIndex;
      // Clear currentMediaInfo when playing content from the sender.
      this.playerHandler.currentMediaInfo = undefined;
    
      // Set video image
      var vi = document.getElementById('video_image');
      vi.src = MEDIA_SOURCE_ROOT + this.mediaContents[mediaIndex]['thumb'];
    
      // Reset progress bar
      var pi = document.getElementById('progress_indicator');
      pi.style.marginLeft = '0px';
      var progress = document.getElementById('progress');
      progress.style.width = '0px';
    
      let seekable_window = document.getElementById('seekable_window');
      let unseekable_overlay = document.getElementById('unseekable_overlay');
      seekable_window.style.width = PROGRESS_BAR_WIDTH;
      unseekable_overlay.style.width = '0px';
    
      // Stop timer and reset time displays
      this.stopProgressTimer();
      this.currentMediaTime = 0;
      this.playerHandler.setTimeString(document.getElementById('currentTime'), 0);
      this.playerHandler.setTimeString(document.getElementById('duration'), 0);
    
      this.playerState = PLAYER_STATE.IDLE;
      this.playerHandler.play();
    };
    
    /**
     * Media seek function
     * @param {Event} event An event object from seek
     */
    CastPlayer.prototype.seekMedia = function (event) {
      if (this.mediaDuration == null || (cast.framework.CastContext.getInstance().getCurrentSession() && !this.remotePlayer.canSeek)) {
        console.log('Error - Not seekable');
        return;
      }
    
      if (this.isLiveContent && !this.liveSeekableRange) {
        console.log('Live content has no seekable range.')
        return;
      }
    
      var position = parseInt(event.offsetX, 10);
      var pi = document.getElementById('progress_indicator');
      var progress = document.getElementById('progress');
      let seekTime = 0;
      let pp = 0;
      let pw = 0;
      if (event.currentTarget.id == 'progress_indicator') {
        seekTime = parseInt(this.currentMediaTime + this.mediaDuration * position /
          PROGRESS_BAR_WIDTH, 10);
        pp = parseInt(pi.style.marginLeft, 10) + position;
        pw = parseInt(progress.style.width, 10) + position;
      } else {
        seekTime = parseInt(position * this.mediaDuration / PROGRESS_BAR_WIDTH, 10);
        pp = position;
        pw = position;
      }
    
      if (this.playerState === PLAYER_STATE.PLAYING ||
        this.playerState === PLAYER_STATE.PAUSED) {
        this.currentMediaTime = seekTime;
        progress.style.width = pw + 'px';
        pi.style.marginLeft = pp + 'px';
      }
    
      if (this.isLiveContent) {
        seekTime += this.mediaInfo.metadata.sectionStartTimeInMedia;
      }
    
      this.playerHandler.seekTo(seekTime);
    };
    
    /**
     * Set current player volume
     * @param {Event} mouseEvent
     */
    CastPlayer.prototype.setVolume = function (mouseEvent) {
      var p = document.getElementById('audio_bg_level');
      var pos = 0;
      if (mouseEvent.currentTarget.id === 'audio_bg_track') {
        pos = FULL_VOLUME_HEIGHT - parseInt(mouseEvent.offsetY, 10);
      } else {
        pos = parseInt(p.clientHeight, 10) - parseInt(mouseEvent.offsetY, 10);
      }
      this.playerHandler.setVolume(pos);
    };
    
    /**
     * Starts the timer to increment the media progress bar
     */
    CastPlayer.prototype.startProgressTimer = function () {
      this.stopProgressTimer();
    
      // Start progress timer
      this.timer = setInterval(this.incrementMediaTimeHandler, TIMER_STEP);
    };
    
    /**
     * Stops the timer to increment the media progress bar
     */
    CastPlayer.prototype.stopProgressTimer = function () {
      if (this.timer) {
        clearInterval(this.timer);
        this.timer = null;
      }
    };
    
    /**
     * Increment media current time depending on remote or local playback
     */
    CastPlayer.prototype.incrementMediaTime = function () {
      // First sync with the current player's time
      this.currentMediaTime = this.playerHandler.getCurrentMediaTime();
      this.mediaDuration = this.playerHandler.getMediaDuration();
    
      this.playerHandler.updateDurationDisplay();
    
      if (this.mediaDuration == null || this.currentMediaTime < this.mediaDuration || this.isLiveContent) {
        this.playerHandler.updateCurrentTimeDisplay();
        this.updateProgressBarByTimer();
      } else if (this.mediaDuration > 0) {
        this.endPlayback();
      }
    };
    
    /**
     * Update progress bar and currentTime based on timer
     */
    CastPlayer.prototype.updateProgressBarByTimer = function () {
      var progressBar = document.getElementById('progress');
      var pi = document.getElementById('progress_indicator');
    
      // Live situation where the progress and duration is unknown.
      if (this.mediaDuration == null) {
        if (!this.isLiveContent) {
          console.log('Error - Duration is not defined for a VOD stream.');
        }
    
        progressBar.style.width = '0px';
        document.getElementById('skip').style.display = 'none';
        pi.style.display = 'none';
    
        let seekable_window = document.getElementById('seekable_window');
        let unseekable_overlay = document.getElementById('unseekable_overlay');
        seekable_window.style.width = '0px';
        unseekable_overlay.style.width = '0px';
        return;
      } else {
        pi.style.display = '';
      }
    
      if (isNaN(parseInt(progressBar.style.width, 10))) {
        progressBar.style.width = '0px';
      }
    
      // Prevent indicator from exceeding the max width. Happens during
      // short media when each progress step is large
      var pp = Math.floor(PROGRESS_BAR_WIDTH * this.currentMediaTime / this.mediaDuration);
      if (pp > PROGRESS_BAR_WIDTH) {
        pp = PROGRESS_BAR_WIDTH;
      } else if (pp < 0) {
        pp = 0;
      }
    
      progressBar.style.width = pp + 'px';
      pi.style.marginLeft = pp + 'px';
    
      let seekable_window = document.getElementById('seekable_window');
      let unseekable_overlay = document.getElementById('unseekable_overlay');
      if (this.isLiveContent) {
        if (this.liveSeekableRange) {
          // Use the liveSeekableRange to draw the seekable and unseekable windows
          let seekableMediaPosition = Math.max(this.mediaInfo.metadata.sectionStartTimeInMedia, this.liveSeekableRange.end) -
            this.mediaInfo.metadata.sectionStartTimeInMedia;
          let seekableWidth = Math.floor(PROGRESS_BAR_WIDTH * seekableMediaPosition / this.mediaDuration);
          if (seekableWidth > PROGRESS_BAR_WIDTH) {
            seekableWidth = PROGRESS_BAR_WIDTH;
          } else if (seekableWidth < 0) {
            seekableWidth = 0;
          }
          seekable_window.style.width = seekableWidth + 'px';
    
          let unseekableMediaPosition = Math.max(this.mediaInfo.metadata.sectionStartTimeInMedia, this.liveSeekableRange.start) -
            this.mediaInfo.metadata.sectionStartTimeInMedia;
          let unseekableWidth = Math.floor(PROGRESS_BAR_WIDTH * unseekableMediaPosition / this.mediaDuration);
          if (unseekableWidth > PROGRESS_BAR_WIDTH) {
            unseekableWidth = PROGRESS_BAR_WIDTH;
          } else if (unseekableWidth < 0) {
            unseekableWidth = 0;
          }
          unseekable_overlay.style.width = unseekableWidth + 'px';
        } else {
          // Nothing is seekable if no liveSeekableRange
          seekable_window.style.width = '0px';
          unseekable_overlay.style.width = PROGRESS_BAR_WIDTH + 'px';
        }
      } else {
        // Default to everything seekable
        seekable_window.style.width = PROGRESS_BAR_WIDTH + 'px';
        unseekable_overlay.style.width = '0px';
      }
    
      if (pp >= PROGRESS_BAR_WIDTH && !this.isLiveContent) {
        this.endPlayback();
      }
    };
    
    /**
     *  End playback. Called when media ends.
     */
    CastPlayer.prototype.endPlayback = function () {
      this.currentMediaTime = 0;
      this.stopProgressTimer();
      this.playerState = PLAYER_STATE.IDLE;
      this.playerHandler.updateDisplay();
    
      document.getElementById('play').style.display = 'block';
      document.getElementById('pause').style.display = 'none';
    };
    
    /**
     * @param {?number} timestamp Linux timestamp
     * @return {?string} media time string. Null if time is invalid.
     */
    CastPlayer.prototype.getMediaTimeString = function (timestamp) {
      if (timestamp == undefined || timestamp == null) {
        return null;
      }
    
      let isNegative = false;
      if (timestamp < 0) {
        isNegative = true;
        timestamp *= -1;
      }
    
      let hours = Math.floor(timestamp / 3600);
      let minutes = Math.floor((timestamp - (hours * 3600)) / 60);
      let seconds = Math.floor(timestamp - (hours * 3600) - (minutes * 60));
    
      if (hours < 10) hours = '0' + hours;
      if (minutes < 10) minutes = '0' + minutes;
      if (seconds < 10) seconds = '0' + seconds;
    
      return (isNegative ? '-' : '') + hours + ':' + minutes + ':' + seconds;
    };
    
    /**
     * @param {number} timestamp Linux timestamp
     * @return {?string} ClockTime string. Null if time is invalid.
     */
    CastPlayer.prototype.getClockTimeString = function (timestamp) {
      if (!timestamp) return "0:00:00";
    
      let date = new Date(timestamp * 1000);
      let hours = date.getHours();
      let minutes = date.getMinutes();
      let seconds = date.getSeconds();
      let ampm = hours >= 12 ? 'PM' : 'AM';
      hours = hours % 12;
      // Hour '0' should be '12'
      hours = hours ? hours : 12;
      minutes = ('0' + minutes).slice(-2);
      seconds = ('0' + seconds).slice(-2);
      let clockTime = hours + ':' + minutes + ':' + seconds + ' ' + ampm;
      return clockTime;
    };
    
    /**
     * Updates Ad markers in UI
     */
    CastPlayer.prototype.updateAdMarkers = function () {
      let castSession = cast.framework.CastContext.getInstance().getCurrentSession();
      if (!castSession) return;
    
      let media = castSession.getMediaSession();
      if (!media) return;
    
      let mediaInfo = media.media;
      if (!mediaInfo) return;
    
      let breaks = mediaInfo.breaks;
      let contentDuration = mediaInfo.duration;
    
      if (!breaks) {
        return;
      }
    
      for (var i = 0; i < breaks.length; i++) {
        let adBreak = breaks[i];
    
        // Server-side stitched Ads (embedded) are skipped when the position is beyond
        // the duration, so they shouldn't be shown with an ad marker on the UI.
        if (adBreak.position > contentDuration && adBreak.isEmbedded) {
          continue;
        }
    
        // Place marker if not already set in position
        if (!document.getElementById('ad' + adBreak.position)) {
          var div = document.getElementById('progress')
          div.innerHTML += '<div class="adMarker" id="ad' + adBreak.position +
            '" style="margin-left: ' +
            this.adPositionToMargin(adBreak.position, contentDuration) + 'px"></div>';
        }
      }
    };
    
    /**
     * Remove Ad markers in UI
     */
    CastPlayer.prototype.removeAdMarkers = function () {
      document.querySelectorAll('.adMarker').forEach(function (adMarker) {
        adMarker.remove();
      });
    };
    
    /**
     * Position of the ad marker from the margin
     */
    CastPlayer.prototype.adPositionToMargin = function (position, contentDuration) {
      // Post-roll
      if (position == -1) {
        return PROGRESS_BAR_WIDTH;
      }
    
      // Client stitched Ads (not embedded) beyond the duration, will play at the
      // end of the content.
      if (position > contentDuration) {
        return PROGRESS_BAR_WIDTH;
      }
    
      // Convert Ad position to margin
      return (PROGRESS_BAR_WIDTH * position) / contentDuration;
    };
    
    /**
     * Handle BREAK_CLIP_ID_CHANGED event
     */
    CastPlayer.prototype.onBreakClipIdChanged = function () {
      // Hide skip button when switching to a new breakClip
      document.getElementById('skip').style.display = 'none';
    };
    
      document.getElementById('progress_indicator').draggable = true;
    
      // Set up feature radio buttons
      let noneRadio = document.getElementById('none');
      noneRadio.onclick = function () {
        ENABLE_LIVE = false;
        ENABLE_ADS = false;
        console.log("Features have been removed");
      }
      let adsRadio = document.getElementById('ads');
      adsRadio.onclick = function () {
        ENABLE_LIVE = false;
        ENABLE_ADS = true;
        console.log("Ads have been enabled");
      }
      let liveRadio = document.getElementById('live');
      liveRadio.onclick = function () {
        ENABLE_LIVE = true;
        ENABLE_ADS = false;
        console.log("Live has been enabled");
      }
    
      if (ENABLE_ADS) {
        if (ENABLE_LIVE) {
          console.error('Only one feature can be enabled at a time. Enabling ads.');
        }
        adsRadio.checked = true;
        console.log("Ads are enabled");
      } else if (ENABLE_LIVE) {
        liveRadio.checked = true;
        console.log("Live is enabled");
      } else {
        noneRadio.checked = true;
        console.log("No features are enabled");
      }
    };
    
    /**
     * Add video thumbnails div's to UI for media JSON contents
     */
    CastPlayer.prototype.addVideoThumbs = function () {
      this.mediaContents = mediaJSON['categories'][0]['videos'];
      var ni = document.getElementById('carousel');
      var newdiv = null;
      var divIdName = null;
      for (var i = 0; i < this.mediaContents.length; i++) {
        newdiv = document.createElement('div');
        divIdName = 'thumb' + i + 'Div';
        newdiv.setAttribute('id', divIdName);
        newdiv.setAttribute('class', 'thumb');
        newdiv.innerHTML =
          '<img src="' + MEDIA_SOURCE_ROOT + this.mediaContents[i]['thumb'] +
          '" class="thumbnail">';
        newdiv.addEventListener('click', this.selectMedia.bind(this, i));
        ni.appendChild(newdiv);
      }
    };
    
    /**
     * Makes human-readable message from chrome.cast.Error
     * @param {chrome.cast.Error} error
     * @return {string} error message
     */
    CastPlayer.getErrorMessage = function (error) {
      switch (error.code) {
        case chrome.cast.ErrorCode.API_NOT_INITIALIZED:
          return 'The API is not initialized.' +
            (error.description ? ' :' + error.description : '');
        case chrome.cast.ErrorCode.CANCEL:
          return 'The operation was canceled by the user' +
            (error.description ? ' :' + error.description : '');
        case chrome.cast.ErrorCode.CHANNEL_ERROR:
          return 'A channel to the receiver is not available.' +
            (error.description ? ' :' + error.description : '');
        case chrome.cast.ErrorCode.EXTENSION_MISSING:
          return 'The Cast extension is not available.' +
            (error.description ? ' :' + error.description : '');
        case chrome.cast.ErrorCode.INVALID_PARAMETER:
          return 'The parameters to the operation were not valid.' +
            (error.description ? ' :' + error.description : '');
        case chrome.cast.ErrorCode.RECEIVER_UNAVAILABLE:
          return 'No receiver was compatible with the session request.' +
            (error.description ? ' :' + error.description : '');
        case chrome.cast.ErrorCode.SESSION_ERROR:
          return 'A session could not be created, or a session was invalid.' +
            (error.description ? ' :' + error.description : '');
        case chrome.cast.ErrorCode.TIMEOUT:
          return 'The operation timed out.' +
            (error.description ? ' :' + error.description : '');
        default:
          return error;
      }
    };
    
    let castPlayer = new CastPlayer();
    window['__onGCastApiAvailable'] = function (isAvailable) {
      if (isAvailable) {
        castPlayer.initializeCastPlayer();
      }
    };

    【讨论】:

    • 感谢@bluejayke,但我需要使用 CastReceiverContext 处理接收器部分
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-20
    • 2022-01-20
    • 2014-06-26
    • 2013-09-06
    • 1970-01-01
    • 2020-12-26
    相关资源
    最近更新 更多