Chromecast 自定义google cast接收器卡在“中”;“正在加载”;
我的定制v3 CAF接收器应用程序正在成功播放前几个live&vod资产。之后,由于“加载正在进行”,它进入媒体命令正在排队的状态。它仍然(成功)获取清单,但媒体_状态仍为“缓冲”。然后,日志显示: [4.537s][cast.receiver.MediaManager]正在加载,媒体命令正在排队 [5.893s][cast.receiver.MediaManager]缓冲状态已更改,isPlayerBuffering:真实旧时间:0当前时间:0 [5.897s][cast.receiver.MediaManager]发送广播状态消息 CastContext核心事件:{“类型”:“媒体状态”,“媒体状态”:{“mediaSessionId”:1,“playbackRate”:1,“playerState”:“缓冲”,“currentTime”:0,“SupportedMediaCommand”:12303,“音量”:{“级别”:1,“静音”:false},“currentItemId”:1,“重复模式”:“重复关闭”,“LiveSeeKablrange”:{“开始”:0,“结束”:20.0009927520752,“isMovingWindow”:true,“IsLivedDone”:false}}} CastContext媒体状态事件:{“类型”:“媒体状态”,“媒体状态”:{“mediaSessionId”:1,“playbackRate”:1,“playerState”:“缓冲”,“currentTime”:0,“SupportedMediaCommand”:12303,“音量”:{“级别”:1,“静音”:false},“currentItemId”:1,“重复模式”:“重复关闭”,“LiveSeeKabrerange”:{“开始”:0,“结束”:20.0009927520752,“isMovingWindow”:true,“isLiveDone”:false}} 获取已完成加载:获取“(清单url)” 没有显示任何错误 即使在关闭并重新启动强制转换会话后,问题仍然存在。强制转换设备本身必须重新启动才能解决问题。看起来在会话之间保留了数据 值得注意的是,cast receiver应用程序尚未发布。它托管在本地网络上 我的问题是:Chromecast 自定义google cast接收器卡在“中”;“正在加载”;,chromecast,google-cast,Chromecast,Google Cast,我的定制v3 CAF接收器应用程序正在成功播放前几个live&vod资产。之后,由于“加载正在进行”,它进入媒体命令正在排队的状态。它仍然(成功)获取清单,但媒体_状态仍为“缓冲”。然后,日志显示: [4.537s][cast.receiver.MediaManager]正在加载,媒体命令正在排队 [5.893s][cast.receiver.MediaManager]缓冲状态已更改,isPlayerBuffering:真实旧时间:0当前时间:0 [5.897s][cast.receiver.M
- 这种卡滞行为的原因可能是什么
- 会话之间是否保留了任何会话数据
- 如何完全重置cast接收器应用程序,而无需重新启动cast设备
const { cast } = window;
const TAG = "CastContext";
class CastStore {
static instance = null;
error = observable.box();
framerate = observable.box();
static getInstance() {
if (!CastStore.instance) {
CastStore.instance = new CastStore();
}
return CastStore.instance;
}
get debugLog() {
return this.framerate.get();
}
get errorLog() {
return this.error.get();
}
init() {
const context = cast.framework.CastReceiverContext.getInstance();
const playerManager = context.getPlayerManager();
playerManager.addEventListener(
cast.framework.events.category.CORE,
event => {
console.log(TAG, "Core event: " + JSON.stringify(event));
}
);
playerManager.addEventListener(
cast.framework.events.EventType.MEDIA_STATUS,
event => {
console.log(TAG, "MEDIA_STATUS event: " + JSON.stringify(event));
}
);
playerManager.addEventListener(
cast.framework.events.EventType.BITRATE_CHANGED,
event => {
console.log(TAG, "BITRATE_CHANGED event: " + JSON.stringify(event));
runInAction(() => {
this.framerate.set(`bitrate: ${event.totalBitrate}`);
});
}
);
playerManager.addEventListener(
cast.framework.events.EventType.ERROR,
event => {
console.log(TAG, "ERROR event: " + JSON.stringify(event));
runInAction(() => {
this.error.set(`Error detailedErrorCode: ${event.detailedErrorCode}`);
});
}
);
// intercept the LOAD request to be able to read in a contentId and get data.
this.loadHandler = new LoadHandler();
playerManager.setMessageInterceptor(
cast.framework.messages.MessageType.LOAD,
loadRequestData => {
this.framerate.set(null);
this.error.set(null);
console.log(TAG, "LOAD message: " + JSON.stringify(loadRequestData));
if (!loadRequestData.media) {
const error = new cast.framework.messages.ErrorData(
cast.framework.messages.ErrorType.LOAD_CANCELLED
);
error.reason = cast.framework.messages.ErrorReason.INVALID_PARAM;
return error;
}
if (!loadRequestData.media.entity) {
// Copy the value from contentId for legacy reasons if needed
loadRequestData.media.entity = loadRequestData.media.contentId;
}
// notify loadMedia
this.loadHandler.onLoadMedia(loadRequestData, playerManager);
return loadRequestData;
}
);
const playbackConfig = new cast.framework.PlaybackConfig();
// intercept license requests & responses
playbackConfig.licenseRequestHandler = requestInfo => {
const challenge = requestInfo.content;
const { castToken } = this.loadHandler;
const wrappedRequest = DrmLicenseHelper.wrapLicenseRequest(
challenge,
castToken
);
requestInfo.content = wrappedRequest;
return requestInfo;
};
playbackConfig.licenseHandler = license => {
const unwrappedLicense = DrmLicenseHelper.unwrapLicenseResponse(license);
return unwrappedLicense;
};
// Duration of buffered media in seconds to start/resume playback after auto-paused due to buffering; default is 10.
playbackConfig.autoResumeDuration = 4;
// Minimum number of buffered segments to start/resume playback.
playbackConfig.initialBandwidth = 1200000;
context.start({
touchScreenOptimizedApp: true,
playbackConfig: playbackConfig,
supportedCommands: cast.framework.messages.Command.ALL_BASIC_MEDIA
});
}
}
LoadHandler可以选择添加一个代理(我正在使用cors anywhere代理删除源标头),并存储licenseRequests的castToken:
class LoadHandler {
CORS_USE_PROXY = true;
CORS_PROXY = "http://192.168.0.127:8003";
castToken = null;
onLoadMedia(loadRequestData, playerManager) {
if (!loadRequestData) {
return;
}
const { media } = loadRequestData;
// disable cors for local testing
if (this.CORS_USE_PROXY) {
media.contentId = `${this.CORS_PROXY}/${media.contentId}`;
}
const { customData } = media;
if (customData) {
const { licenseUrl, castToken } = customData;
// install cast token
this.castToken = castToken;
// handle license URL
if (licenseUrl) {
const playbackConfig = playerManager.getPlaybackConfig();
playbackConfig.licenseUrl = licenseUrl;
const { contentType } = loadRequestData.media;
// Dash: "application/dash+xml"
playbackConfig.protectionSystem = cast.framework.ContentProtection.WIDEVINE;
// disable cors for local testing
if (this.CORS_USE_PROXY) {
playbackConfig.licenseUrl = `${this.CORS_PROXY}/${licenseUrl}`;
}
}
}
}
}
DrmHelper包装许可证请求以添加castToken,base64对整个请求进行编码。许可证响应随后进行base64解码和取消包装:
export default class DrmLicenseHelper {
static wrapLicenseRequest(challenge, castToken) {
const wrapped = {};
wrapped.AuthToken = castToken;
wrapped.Payload = fromByteArray(new Uint8Array(challenge));
const wrappedJson = JSON.stringify(wrapped);
const wrappedLicenseRequest = fromByteArray(
new TextEncoder().encode(wrappedJson)
);
return wrappedLicenseRequest;
}
static unwrapLicenseResponse(license) {
try {
const responseString = String.fromCharCode.apply(String, license);
const responseJson = JSON.parse(responseString);
const rawLicenseBase64 = responseJson.license;
const decodedLicense = toByteArray(rawLicenseBase64);
return decodedLicense;
} catch (e) {
return license;
}
}
}
cast.framework.messages.MessageType.LOAD的处理程序应始终返回:
- (可能已修改)
loadRequestData
,或
- 对(可能修改的)
loadRequestData的承诺
null
放弃加载请求(我不能100%确定这对加载请求有效)
如果不这样做,加载请求将留在队列中,任何新请求都将在初始请求之后排队
在处理程序中,如果!loadRequestData.media
,您将返回一个错误,这将使您进入该状态。另一种可能是加载请求处理程序中出现异常,这也将使您处于该状态。我想我们有不同的方法,在加载内容时,通过发送消息
发送所有可能的内容e创建一个new cast.framework.messages.LoadRequestData()
,我们使用playerManager.load(loadRequest)
加载它
但我想你可能正在集成Chromecast上测试,我们也看到了这个问题
我建议你做一个或多个
- 对所有响应启用gzip压缩
- 停止播放
playerManager.Stop()
(可能在中间接收器中?)
- 更改
licenseUrl
的设置方式
我们如何设置许可证URL
playerManager.setMediaPlaybackInfoHandler((loadRequestData, playbackConfig) => {
playbackConfig.licenseUrl = loadRequestData.customData.licenseUrl;
return playbackConfig;
}
);
您好。我有类似的问题,但没有修复jet。您能回答以下问题吗:您使用的是什么设备?google cast的版本是什么?媒体格式是什么?您是否定义广告中断?我主要是向内置chromecast的安卓电视盒进行播放。问题似乎不是特定于设备的。chromecast版本目前是1.36.168363。流媒体协议ol为仪表板(和widevine DRM)。没有广告中断。今天我们很幸运地删除了cookie以解除设备阻塞。明天我们将对此进行彻底检查,并提出有关加载处理程序的建议。谢谢。因此,会话是从cookie中保留和还原的?什么是
加载处理程序
?谢谢。除此之外,是否有方法以干净状态启动强制转换会话?这是为什么在结束“卡住”会话后保持状态?我认为不可能从接收器重新启动cast会话以进入干净状态。根据我的经验,CAF在处理截获请求的方式上不是很灵活。处理负载请求尤其令人痛苦,尤其是在需要异步执行的情况下d支持在前一个加载请求尚未完成时处理新的加载请求。这可能是触发卡住的“加载进行中”的另一个场景。。。