- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我在使用新的 CAF 接收器时遇到问题,无法将 YouTube iframe 播放器注册为播放器,但它正在播放。连接到接收器5分钟后,连接断开,因为它认为播放器空闲。
这是发件人代码
var metadata = new chrome.cast.media.GenericMediaMetadata();
metadata.title = "Foo - Bar";
metadata.image = 'https://img.youtube.com/vi/IXNrHusLXoM/mqdefault.jpg';
metadata.images = ['https://img.youtube.com/vi/IXNrHusLXoM/mqdefault.jpg'];
var mediaInfo = new chrome.cast.media.MediaInfo();
mediaInfo.contentType = "video/*";
mediaInfo.contentId ="IXNrHusLXoM";
mediaInfo.duration = 300;
var request = new chrome.cast.media.LoadRequest();
request.media = mediaInfo;
request.customData = customData;
request.metadata = metadata;
castSession.loadMedia(request).then(
function() {
console.log('Load succeed');
},
function(errorCode) {
console.log('Error code: ' + errorCode);
});
接收器代码可以在这里找到:https://github.com/zoff-music/zoff-chromecast-receiver/blob/feature/v3/receiver.js
有没有办法让新的 CAF 接收器挂接到 YouTube iframe 播放器,或者“手动”调度 LOADED、BUFFERING、PLAYING、PAUSED、STOPPED 事件,以便接收器不会与发送器断开连接?
编辑:使用上面的代码,PlayerState 到达 BUFFERING 阶段,但停在那里。带有日志“Load success”的 promise 永远不会被触发。
最佳答案
我设法用假的 mediaEelement 欺骗了接收者。可以看到代码in pastebin
const context = cast.framework.CastReceiverContext.getInstance();
const playerManager = context.getPlayerManager();
var yt_events = {};
var pause_request = false;
var yt_player;
var yt_video_fake = {
removeAttribute: function(attr) {
},
setAttribute: function(attr, val) {
},
getCurrentTimeSec: function() { return yt_player && yt_player.getCurrentTime ? yt_player.getCurrentTime() : 0; },
getDurationSec: function() { return yt_player ? yt_player.getDuration() : 0; },
getVolume: function() {
if(!yt_player || !yt_player.getVolume) {
return 0;
}
var volume = new cast.framework.messages.Volume();
volume.level = yt_player.getVolume() / 100;
volume.muted = yt_player.isMuted() ? true : false;
return volume;
},
setVolume: function(vol) { yt_player && yt_player.setVolume(vol.level * 100); },
getState: function() {
if(!yt_player || !yt_player.getPlayerState) {
return 'IDLE';
}
var state = yt_player.getPlayerState();
var _state;
if(pause_request) {
pause_request = false;
state = YT.PlayerState.PAUSED;
}
switch(state) {
default: case YT.PlayerState.UNSTARTED:
_state = 'IDLE';
break;
case YT.PlayerState.PLAYING:
_state = 'PLAYING';
break;
case YT.PlayerState.PAUSED:
_state = 'PAUSED';
break;
case YT.PlayerState.BUFFERING:
_state = 'BUFFERING';
break;
case YT.PlayerState.ENDED:
_state = 'ENDED';
break;
}
return _state;
},
addEventListener: function(e, func) { },
load: function() {},
play: function() { yt_player && yt_player.playVideo(); },
pause: function() { if(yt_player && yt_player.pauseVideo) {pause_request = true; yt_player.pauseVideo(); }},
seek: function(timeTo) { yt_player && yt_player.seekTo(timeTo, true);},
reset: function() {
if(yt_player) {
try { yt_player.destroy && yt_player.destroy(); } catch(e) {
//console.trace(e);
};
delete yt_player;
}
},
registerErrorCallback: function(func) { yt_events['error'] = func; },
registerEndedCallback: function(func) { yt_events['ended'] = func; },
registerLoadCallback: function(func) { yt_events['load'] = func; },
unregisterErrorCallback: function () { delete yt_events['error'] },
unregisterEndedCallback: function () { delete yt_events['ended']},
unregisterLoadCallback: function () { delete yt_events['load']}
};
Object.defineProperty(yt_video_fake, 'currentTime', {
val1: null,
get: function() { return yt_player && yt_player.getCurrentTime ? yt_player.getCurrentTime() : this.val1; },
set: function(newValue) {
yt_player && yt_player.seekTo(newValue, true);
this.val1 = newValue;
},
enumerable : true,
configurable : true
});
Object.defineProperty(yt_video_fake, 'volume', {
val1: null,
get: function() { var vol = this.getVolume(); if(vol) return vol['level']; return 1; },
set: function(newValue) {
yt_player && yt_player.setVolume && yt_player.setVolume(newValue * 100);
this.val1 = newValue;
},
enumerable : true,
configurable : true
});
Object.defineProperty(yt_video_fake, 'duration', {
val1: null,
get: function() { return this.getDurationSec(); },
set: function() {},
enumerable : true,
configurable : true
});
function YoutubePlayMedia(videoid) {
var yt_container = $('#yt_container');
if(!yt_container.length) {
yt_container = $('<div id="yt_container" style="position:absolute;top:0;left:0;width:100%;height:100%;"></div>');
$('body').append(yt_container);
}
yt_container.html('<iframe id="youtube_container" style="width:100%;height:100%;" frameborder="0" allowfullscreen="1" allow="autoplay; encrypted-media" title="YouTube video player" src="//www.youtube.com/embed/' + videoid +'?autoplay=1&enablejsapi=1&modestbranding=1&controls=0&fs=0&iv_load_policy=3&rel=0&cc_load_policy=1&cc_lang_pref=bg"></iframe>');
yt_player = new YT.Player('youtube_container', {
events: {
'onReady': function(e) {
yt_player.is_loaded = true;
yt_player.playVideo();
},
'onStateChange': function(e) {
switch(e.data) {
case YT.PlayerState.PLAYING:
if(yt_player.is_loaded) {
if(yt_events['load']) {
yt_events['load']();
}
}
break;
case YT.PlayerState.ENDED:
//yt_events['ended'] && yt_events['ended'](e);
break;
}
},
'onError': function(e) {
//yt_events['error'] && yt_events['error'](e);
}
}
});
}
function YoutubeLoadMedia(url) {
current_media_type = 'Youtube';
window.onYouTubeIframeAPIReady = function() {
window.youtube_loaded = true;
YoutubePlayMedia(url);
}
if(!window.youtube_script) {
window.youtube_script = document.createElement('script');
window.youtube_script.src = "https://www.youtube.com/iframe_api";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(window.youtube_script, firstScriptTag);
} else {
// Вече имаме api направо действаме
YoutubePlayMedia(url);
}
}
playerManager.setMessageInterceptor(
cast.framework.messages.MessageType.LOAD,
loadRequestData => {
if (loadRequestData.media && loadRequestData.media.contentId) {
YoutubeLoadMedia(loadRequestData.media.contentId);
playerManager.setMediaElement(yt_video_fake);
return false;
}
return loadRequestData;
}
);
const options = new cast.framework.CastReceiverOptions();
options.disableIdleTimeout = true;
context.start(options);
关于javascript - Chromecast 定制 CAF 接收器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49017723/
我目前被指派去调查并以某种方式找到一种“定制”(对身份验证、常量、消息等进行修改)OpenSSH 的方法,并且作为一个“基于网络”的人,我真的不知道从哪儿开始。因此非常感谢评论。 问题: 我从 her
我拥有的 excel 文件超过 1,000,000 行和 26 列。 下面是用于查找特定数据的代码,并根据该数据创建一个新文件,目前创建一个新文件大约需要 15 分钟 请如果有专家可以帮助我更快地处理
我正在处理Zend_Form现在,我很难弄清楚如何: 使用表单按钮的自定义图像, 在特定位置插入文本和链接(就我而言,我想在提交按钮之前添加“忘记密码?”链接)。 我已通读手册,但没有看到任何相关内容
是否可以将图像添加到 UISwitch 背景,例如当状态为 ON 时(作为一个背景)和当状态为 OFF 时(另一个背景图像)? 最佳答案 要更改背景颜色(不是图像),您只需执行以下操作即可。这会更改领
到目前为止,我刚刚开始使用 Octave 并在我的终端上运行它。 每次打开提示符时,我的命令行都以: octave-3.4.0:1> 因此我使用以下内容来使其更短且更易于阅读: PS1('>> ')
在阅读Struts2文档时,我遇到了下面引用的段落 customizing controller - Struts 1 lets to customize the request processor
我正在尝试自定义 jQuery Tag-It 小部件 (http://aehlke.github.com/tag-it/) 以实现以下两种行为: 1)允许在标签中使用逗号(我可以通过自定义trigge
我是整个 Emacs 的新手,让我着迷的一件事是开箱即用的 Emacs 在编程时不会让您陷入困境。我主要使用 Python 和 C++ 进行编程,然后按回车键将光标发送回新行的第 1 列,而不是让你停
我有这些行 y DB,我想按以下顺序排序,并包含字符和数字。 Score 列是一个 varchar。获胜者和失败者也在分数栏中。 得分 WINNER 100+ 100 90 80+ 80 50 LOS
我正在使用 Bootstrap,您如何自定义轮播? 有什么建议吗? https://v4-alpha.getbootstrap.com/components/carousel/ 最佳答案 .activ
我有一个投票设置,使用脚本将其拉入我的 WP 页面。通过http://quipol.com/ EG 我已经通过 firebug 找到了样式并在其中相应地自定义了它们,但我想知道是否有一种方法可以实现
美好的一天。 如果 JLabel 和 JTextField 字体大小可以根据需要更改,是否也可以更改 JTable 的列名称和元素的字体样式(大小、外观、颜色)? 添加更多内容,我正在使用 Windo
进一步回答我的问题Java JFilechooser 。建议扩展 BasicFileChooserUI,重写 create/getModel 并提供 BasicDirectoryModel 的实现。
我想制作(好吧..正在制作..)一个标签页。我用 border-top:none 属性制作了一个“选项卡框”,所以它看起来像是选项卡的一部分,在里面我有一个表格。 我想知道,有没有办法删除表格标题的所
我有大量的项目正在进行中,还有几个解决方案(它们是项目“池”的子集)。有时拥有一个仅用于特定测试的 .sln 是件好事。 问题: NUGet 分别绑定(bind)到每个解决方案。 NUGet 喜欢在
我计划编写一些 git 钩子(Hook)作为一个项目,将用户的操作记录在数据库中。然后可以使用该数据库查询他的所有事件。我尝试记录的操作是 promise pull 推送 merge 分支机构 我想把
大家好,我是张飞洪,感谢您的阅读,我会不定期和你分享学习心得,希望我的文章能成为你成长路上的垫脚石,让我们一起精进。 在本文中,我们将学习中间件,以及如何使用它进一步定制应用程序。我
我正在尝试使用 yasg 自定义我的 api 文档。 首先,我想确定我自己的部分的命名,以及本部分应包含哪些端点。似乎部分的命名是基于不属于最长公共(public)前缀的第一个前缀,例如: 如果我们有
我需要(即客户要求)提供自定义键盘,供用户在文本字段和区域中输入文本。我已经有一些可以执行键盘操作并将测试附加到文本字段的东西,但是我想让它更通用并让它像标准的 iphone 键盘一样工作,即当用户选
我有一个项目,它在特定位置(不是/src/resources)包含资源(模板文件)。我希望在运行 package-bin 时将这些资源打包。 我看到了 package-options 和 packag
我是一名优秀的程序员,十分优秀!