I used to play youtube in my iOS app with the HTML string as below.
I used to load the HTML as
[webView loadHTMLString:fileContents baseURL:[[NSBundle mainBundle] resourceURL]];
Suddenly it has stopped working. The only way it works is if I set the baseURL to a http URL like "http://www.example.com". I want to know what is the correct baseURL to set.
<div id='container'>
<div id="child">
<div id="player"></div>
</div>
</div>
<script>
var tag = document.createElement('script');
tag.src = "https://www.youtube.com/iframe_api";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
var player;
function onYouTubeIframeAPIReady() {
player = new YT.Player('player', {
width: '%#',
height: '%#',
videoId: '%#',
playerVars: {
origin: 'file://',
showinfo: 0,
controls: 0,
playsinline: 1,
autoplay: 1
},
events: {
'onReady': onPlayerReady,
'onStateChange': onPlayerStateChange,
'onPlaybackQualityChange': onPlayerPlaybackQualityChange,
'onPlaybackRateChange': onPlayerPlaybackRateChange,
'onError': onPlayerError,
'onApiChange': onPlayerApiChange
}
});
}
// Event functions
function onPlayerReady(event) {
onEvent('ready', null);
}
function onPlayerStateChange(event) {
onEvent('stateChange', playerStateToString(event.data));
}
function onPlayerPlaybackQualityChange(event) {
onEvent('playbackQuality', event.data);
}
function onPlayerPlaybackRateChange(event) {
onEvent('playbackRateChange', event.data);
}
function onPlayerError(event) {
onEvent('error', event.data);
}
function onPlayerApiChange(event) {
onEvent('apiChange', event.data);
}
function onEvent(eventName, eventData) {
var url = "ytplayer://event/" + eventName;
if (eventData != null) {
url += ('/' + eventData);
}
document.location = url;
}
// Helpers
function playerStateToString(playerState) {
var result = null;
switch (playerState) {
case -1:
result = "unstarted";
break;
case YT.PlayerState.ENDED:
result = "ended";
break;
case YT.PlayerState.PLAYING:
result = "playing";
break;
case YT.PlayerState.PAUSED:
result = "paused";
break;
case YT.PlayerState.BUFFERING:
result = "buffering";
break;
case YT.PlayerState.CUED:
result = "cued";
break;
}
return result;
}
</script>
"
I use "about:blank". This value just cannot be null or NONE.
Related
Background video loads properly and autoplays etc. when the page is first loaded (and when refreshed) but when navigating to the page via the navbar links the video wont load.
Site is using Ruby on Rails if that makes any difference.
I suspect my issue is somewhere in the js but I'm new to this and haven't been able to sort out what isn't triggering
Script for the video:
// Video Script //
var tag = document.createElement('script');
tag.src = "https://www.youtube.com/iframe_api";
// Inserts YouTube JS code into the page.
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
var player;
// onYouTubeIframeAPIReady() is called when the IFrame API is ready to go.
function onYouTubeIframeAPIReady() {
player = new YT.Player('player', {
height: '360',
width: '640',
videoId: '7copSLUofm8',
playerVars: { 'autoplay': 1, 'controls': 0, 'showinfo': 0, 'rel': 0, 'enablejsapi':1, 'wmode' : 'transparent'},
events : {
'onReady' : pkOnPlayerReady,
'onStateChange' : pkOnPlayerStateChange
}
});
}
function pkOnPlayerStateChange(e) {
var frm = $(e.target.getIframe());
if (e.data === YT.PlayerState.ENDED) {
if ('player' === frm.attr('id')) {
player.playVideo();
}
}
if (e.data === YT.PlayerState.BUFFERING) {
if ('player' === frm.attr('id')) {
e.target.setPlaybackQuality('hd720');
}
}
}
function pkOnPlayerReady(e) {
player.mute();
e.target.setPlaybackQuality('hd720');
}
//Load a youtube pixel
var pkEnableYoutube = function() {
var deferred = jQuery.Deferred();
var img = new Image();
img.onload = function() { return deferred.resolve(); };
img.onerror = function() { return deferred.reject(); };
img.src = "https://s.ytimg.com/yts/img/pixel-vfl3z5WfW.gif?"+ new Date().getTime();
return deferred.promise();
};
//When the video starts to load, set a timer for the video wrap to fade in
jQuery(function($){
$.when(pkEnableYoutube()).done(function(){
setTimeout(function() {
$('.video_wrap').fadeIn();
}, 2000);
});
});
I have been working on the receiver in the google cast sdk. I have mutiple youtube videos and mp4 videos in cloud and i have an app that has these videos. I am able to able to cast the youtube videos but when i click on the mp4 link i cannot get back control to the receiver.
Anybody any help?`
var player;
function onYouTubePlayer(videoId) {
player = new YT.Player('player', {
height: '720',
width: '1280',
videoId: videoId,
playerVars: { autoplay:1, controls:1, showinfo: 0, rel: 0, showsearch: 0, iv_load_policy: 3, enablejsapi:1,listType:'playlist',
list: playlist},
events: {
'onReady': onPlayerReady,
'onStateChange': onPlayerStateChange,
'onError': catchError
}
});
}
var done = false;
var playlist;
function onPlayerStateChange(event) {
if (event.data == YT.PlayerState.PLAYING && !done) {
done = true;
} else if (event.data == YT.PlayerState.ENDED) {
event.target.destroy();
location.reload();
}else if(event.data == YT.PlayerState.PAUSED){
location.reload();
}
}
function onPlayerReady(event) {
//if(typeof(SONG.getArtistId()) == undefined)
//{
// console.log("undefineeeed");
//}
player.addEventListener('onStateChange', function(e) {
console.log('State is:', e.data);
});
event.target.playVideo();
}
function catchError(event)
{
if(event.data == 100) console.log("This Video does not exist!!");
}
function stopVideo() {
player.stopVideo();
}
/**
* Called when we receive a LOAD message. Calls load().
*
* #see sampleplayer#load
* #param {cast.receiver.MediaManager.Event} event The load event.
* #private
*/
sampleplayer.CastPlayer.prototype.onLoad_ = function(event) {
this.log_('onLoad_');
this.log_(event.data);
// handler for the CastMessageBus message event
this.messageBus.onMessage = function(event) {
this.log_('Message [' + event.senderId + ']: ' + event.data);
// display the message from the sender
// inform all senders on the CastMessageBus of the incoming message event
// sender message listener will be invoked
this.messageBus.send(event.senderId, event.data);
}
var videoId = event.data.media.contentId.split("?v=")[1];
if(event.data.media.contentId.includes("youtube.com")){
if (typeof(YT) == 'undefined' || typeof(YT.Player) == 'undefined') {
var tag = document.createElement('script');
tag.src = "https://www.youtube.com/iframe_api";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
window.onYouTubePlayerAPIReady = function() {
onYouTubePlayer(videoId);
};
} else {
onYouTubePlayer(videoId);
}
}else{
}
this.cancelDeferredPlay_('new media is loaded');
this.load(new cast.receiver.MediaManager.LoadInfo(
/** #type {!cast.receiver.MediaManager.LoadRequestData} */ (event.data),
event.senderId));
};
`
I've looked through so many questions and the youtube api stuff but for the life of me can't figure out why the onYouTubeIframeAPIReady is not working.
Here is my iframe:
<iframe id="youtube_vid" width="763" height="430" src="https://www.youtube.com/embed/dlJshzOv2cw?theme=light&showinfo=0&rel=0&enablejsapi=1" frameborder="0" allowfullscreen=""></iframe>
And my script:
function callYTapi() {
var tag = document.createElement('script');
tag.src = "https://www.youtube.com/iframe_api";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
console.log('script loaded');
function onYouTubeIframeAPIReady() {
console.log('IframeAPI = Ready');
var player = new YT.Player('youtube_vid', {
events: {
'onReady': onPlayerReady,
'onStateChange': onPlayerStateChange
}
});
}
function onPlayerReady(event) {
event.target.playVideo();
}
function onPlayerStateChange(event) {
if (event.data == YT.PlayerState.PAUSED) {
console.log("Paused");
}
if (event.data == YT.PlayerState.PLAYING) {
console.log("Playing");
}
if (event.data == YT.PlayerState.ENDED) {
end();
}
}
}
I get the console.log for the loaded script but not for Iframe ready or anything else. Any ideas? Thanks
The callback functions must be in the global scope. Just move onYouTubeIframeAPIReady and the others outside callYTapi.
Just to be clear, the accepted answer above seems to work for me in this way:
Load API (from yt documentation)
var tag = document.createElement('script');
tag.src = "https://www.youtube.com/iframe_api";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
specify YouTube's built-in ready function "onYouTubeIframeAPIReady" on window
window.onYouTubeIframeAPIReady = this.onYTready;
So this.onYTready is my function name and located elsewhere.
I can confirm my onYTready function can console logs/debugger breakpoints in Chrome.
(edit) you may want to bind this to your function, example:
window.onYouTubeIframeAPIReady = this.onYTready.bind(this);
or 'this' will be for window instead of a specific view you may be using..
Fortunately for me, after a lot of experimenting with console, I had something concrete. I kind of had the same issue until a day ago and figured out how to do when I was within a singleton scope.
Here is what my code looks like:
var XT = XT || {};
window.onYouTubeIframeAPIReady = function(){
setTimeout(XT.yt.onYouTubeIframeAPIReady,500);
}
XT.yt = {
/* load the YouTube API first */
loadApi: function () {
var j = document.createElement("script"),
f = document.getElementsByTagName("script")[0];
j.src = "//www.youtube.com/iframe_api";
j.async = true;
f.parentNode.insertBefore(j, f);
console.log('API Loaded');
},
/*default youtube api listener*/
onYouTubeIframeAPIReady: function () {
console.log('API Ready?');
window.YT = window.YT || {};
if (typeof window.YT.Player === 'function') {
player = new window.YT.Player('player', {
width: '640',
height: '390',
videoId: 'nE6mDCdYuwY',
events: {
onStateChange: XT.yt.onPlayerStateChange,
onError: XT.yt.onPlayerError,
onReady: setTimeout(XT.yt.onPlayerReady, 4000)
}
});
}
},
onPlayerReady: function() {
player.playVideo(); /* start the video */
player.setVolume(1); /* set volume to 1 (accepts 0-100) */
},
onPlayerStateChange: function (e) {
console.log(e.data, YT.PlayerState.PLAYING, e.data === YT.PlayerState.PLAYING);
var video_data = e.target.getVideoData();
//do something on video ends
if(e.data === YT.PlayerState.ENDED)
this.onPlayerStop();
},
onPlayerStop: function(){
//console.log('video ended');
},
onPlayerError: function (e) {
console.log( "youtube: " + e.target.src + " - " + e.data);
},
init: function () {
this.loadApi();
}
}
XT.yt.init();
function playIframeVideo(iframe) {
iframe.videoPlay = true; //init state
iframe.contentWindow.postMessage('{"event":"command","func":"playVideo","args":""}', '*');
}
function pauseIframeVideo(iframe) {
iframe.videoPlay = false; //init state
iframe.contentWindow.postMessage('{"event":"command","func":"pauseVideo","args":""}', '*');
}
$('.vc_video-bg-container').on('click', function () {
var iframe = $('iframe').get(0); //iframe tag
if (iframe.videoPlay != true) {
playIframeVideo(iframe);
} else {
pauseIframeVideo(iframe);
}
});
I need to know when a youtube video has stopped playing. I looked up existing Q&As and all of them suggested redirecting to another unique URL which can be detected in webview load finished delegate.
But to do this I need to have a HTML page on server or in my app(since I need to add javascript functions for onStateChange). If its on server, server downtime will affect the app, if its in the app, any change would require an app update.
Is there any other workaround for this ?
EDIT: JS code which needs to be injected/loaded in html.
var player;
var videoID;
var prmstr = window.location.search.substr(1);
var prmarr = prmstr.split ("&");
var params = {};
for ( var i = 0; i < prmarr.length; i++) {
var tmparr = prmarr[i].split("=");
params[tmparr[0]] = tmparr[1];
}
if (params.videoID !== undefined || params.videoID !== "") {
videoID = params.videoID;
} else {
videoID = "0Bmhjf0rKe8";
}
function onYouTubePlayerAPIReady() {
player = new YT.Player('player', {
height: '390',
width: '640',
videoId: videoID,
events: {
'onReady': onPlayerReady,
'onStateChange': onPlayerStateChange
}
});
}
// autoplay video
function onPlayerReady(event) {
event.target.playVideo();
}
// when video ends
function onPlayerStateChange(event) {
if(event.data === 0) {
window.location.href = "http://example.com/done.html";
}
}
I have a jCarousel (jquery) running for several youtube videos. The carousel works great, and even pauses when you hover on a slide- but it will resume if you move your cursor off the slide, even if the video is playing.
Videos are embedded using the YouTube Player API.
Plugin: http://sorgalla.com/jcarousel/
This is the Carousel code I'm using:
<script type="text/javascript">
function mycarousel_initCallback(carousel, item, idx, state){
// Disable autoscrolling if the user clicks the prev or next button.
carousel.buttonNext.bind('click', function() {
carousel.startAuto(0);
});
carousel.buttonPrev.bind('click', function() {
carousel.startAuto(0);
});
// Pause autoscrolling if the user moves with the cursor over the clip.
$('#mycarousel').hover(function() {
carousel.stopAuto();
}, function() {
carousel.startAuto();
});
};
$(function() {
$('#mycarousel').jcarousel({
auto: 2,
wrap: 'both',
initCallback: mycarousel_initCallback
});
});
</script>
The YouTube script:
<script>
var tag = document.createElement('script');
tag.src = "http://www.youtube.com/player_api";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
var done = false;
var player;
function onYouTubePlayerAPIReady() {
player = new YT.Player('player', {
height: '505', // 535
width: '900',
videoId: 'DxZve0UV6UM',
playerVars: {
'autoplay': 0,
'controls': 0,
'modestbranding': 1,
'wmode': 'opaque'
},
events: {
'onReady': onPlayerReady,
'onStateChange': onPlayerStateChange
}
});
}
function onPlayerReady(evt) {
player.setPlaybackQuality('hd720');
}
function onPlayerStateChange(evt) {
if (evt.data == YT.PlayerState.PLAYING && !done) {
done = true;
}
}
function stopVideo() {
player.stopVideo();
}
</script>
And the HTML...
<ul id="mycarousel" class="jcarousel-skin-tango">
<li>
<div id="player"></div>
</li>
<li>
<div id="player"></div>
</li>
</ul>
Any suggestions?
Simply call carousel.startAuto() and carousel.stopAuto() when the player triggers an event:
function onPlayerStateChange(evt) {
if(evt.data == YT.PlayerState.PLAYING) {
global_carousel.stopAuto(); // Stop the carousel, if video is playing
} else {
global_carousel.startAuto(); // Otherwise, start it
}
}
Edit:
Make the variable carousel global inside mycarousel_initCallback:
var global_carousel;
function mycarousel_initCallback(carousel, item, idx, state) {
global_carousel = carousel;
//Other code
Then use that instead in the code before (as I've edited).