默认命名空间在 chromecast 接收器中调用
Posted
技术标签:
【中文标题】默认命名空间在 chromecast 接收器中调用【英文标题】:Default namespace is calling in chromecast receiver 【发布时间】: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
【问题讨论】:
【参考方案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 处理接收器部分以上是关于默认命名空间在 chromecast 接收器中调用的主要内容,如果未能解决你的问题,请参考以下文章
Chromecast v3|安卓 |如何使用自定义命名空间?