I am needing to have some info passed to scripts when onPlayerStateChange() function fires off.
What I am after is the current videoID of the currently playing video and the array position number from the playlist.
(-_-)ZZZzzz...
EDIT....
Ok. So I have progressed a bit.
In the player code, I have this fire off
if (event.data == -1) {
getPlaylistIndex();
}
I then have this script.
function getPlaylistIndex() {
var str = ""+ytplayer.getPlaylist();
var viedoString = str.split(',');
var videoID = viedoString[ytplayer.getPlaylistIndex()];
if(videoID == undefined){
} else {
alert(videoID);
loadComents(videoID);
loadVideoINFO(videoID);
}
}
You will notice an IF condition which is needed to not fire the code for normal videos... just on the PL's.
It is working apart from the fact that when I load the playlist in, I do not get a videoID from the script. If I select any video in the playlist and also go back to the first one, it works fine. Just not working when first loading the playlist.
Any ideas ?
P.S. the alert is for testing only.
RE-EDIT.... ;P
Ok. I have been playing with this for the whole day going in and out of all scripts.
I have it working now (so it seems).
First I added into my code to give me this.
function getPlaylistIndex() {
var str = ""+ytplayer.getPlaylist();
var viedoString = str.split(',');
var videoID = viedoString[ytplayer.getPlaylistIndex()];
if(videoID == undefined){
} else {
if(videoID == ''){
var str2 = ytplayer.getVideoUrl();
videoID = (str2.substring(31,42));
}
loadComents(videoID);
loadVideoINFO(videoID);
}
}
And so it works first time, I needed to change
event.data == -1 to event.data == 1 as YTplayer fires them in a particular order.
If anyone has anything to ad or correct, please do so.
Related
I am trying to get audio capture from the microphone working on Safari on iOS11 after support was recently added
However, the onaudioprocess callback is never called. Here's an example page:
<html>
<body>
<button onclick="doIt()">DoIt</button>
<ul id="logMessages">
</ul>
<script>
function debug(msg) {
if (typeof msg !== 'undefined') {
var logList = document.getElementById('logMessages');
var newLogItem = document.createElement('li');
if (typeof msg === 'function') {
msg = Function.prototype.toString(msg);
} else if (typeof msg !== 'string') {
msg = JSON.stringify(msg);
}
var newLogText = document.createTextNode(msg);
newLogItem.appendChild(newLogText);
logList.appendChild(newLogItem);
}
}
function doIt() {
var handleSuccess = function (stream) {
var context = new AudioContext();
var input = context.createMediaStreamSource(stream)
var processor = context.createScriptProcessor(1024, 1, 1);
input.connect(processor);
processor.connect(context.destination);
processor.onaudioprocess = function (e) {
// Do something with the data, i.e Convert this to WAV
debug(e.inputBuffer);
};
};
navigator.mediaDevices.getUserMedia({audio: true, video: false})
.then(handleSuccess);
}
</script>
</body>
</html>
On most platforms, you will see items being added to the messages list as the onaudioprocess callback is called. However, on iOS, this callback is never called.
Is there something else that I should do to try and get it called on iOS 11 with Safari?
There are two problems. The main one is that Safari on iOS 11 seems to automatically suspend new AudioContext's that aren't created in response to a tap. You can resume() them, but only in response to a tap.
(Update: Chrome mobile also does this, and Chrome desktop will have the same limitation starting in version 70 / December 2018.)
So, you have to either create it before you get the MediaStream, or else get the user to tap again later.
The other issue with your code is that AudioContext is prefixed as webkitAudioContext in Safari.
Here's a working version:
<html>
<body>
<button onclick="beginAudioCapture()">Begin Audio Capture</button>
<script>
function beginAudioCapture() {
var AudioContext = window.AudioContext || window.webkitAudioContext;
var context = new AudioContext();
var processor = context.createScriptProcessor(1024, 1, 1);
processor.connect(context.destination);
var handleSuccess = function (stream) {
var input = context.createMediaStreamSource(stream);
input.connect(processor);
var recievedAudio = false;
processor.onaudioprocess = function (e) {
// This will be called multiple times per second.
// The audio data will be in e.inputBuffer
if (!recievedAudio) {
recievedAudio = true;
console.log('got audio', e);
}
};
};
navigator.mediaDevices.getUserMedia({audio: true, video: false})
.then(handleSuccess);
}
</script>
</body>
</html>
(You can set the onaudioprocess callback sooner, but then you get empty buffers until the user approves of microphone access.)
Oh, and one other iOS bug to watch out for: the Safari on iPod touch (as of iOS 12.1.1) reports that it does not have a microphone (it does). So, getUserMedia will incorrectly reject with an Error: Invalid constraint if you ask for audio there.
FYI: I maintain the microphone-stream package on npm that does this for you and provides the audio in a Node.js-style ReadableStream. It includes this fix, if you or anyone else would prefer to use that over the raw code.
Tried it on iOS 11.0.1, and unfortunately this problem still isn't fixed.
As a workaround, I wonder if it makes sense to replace the ScriptProcessor with a function that takes the steam data from a buffet and then processes it every x milliseconds. But that's a big change to the functionality.
Just wondering... do you have the setting enabled in Safari settings? It comes enabled by default in iOS11, but maybe you just disabled it without noticing.
Is it possible to stop a video using the YouTube API one second before the end or just stopping it resetting back to the beginning? This is regardless of the length of the video itself.
Thanks in advance
I disagree with the argument of NOT being able to stop a video before it ends. Specifically, in the API, you have access to:
https://developers.google.com/youtube/js_api_reference#Playback_status
Player.getCurrentTime();
Player.getDuration();
If you were to monitor the player object and compare these two, you could easily stop the video before it ends. An example would be (although probably not good in production):
setInterval(function() {
var player = getPlayer(); //retrieve the player object
if(player) {
var duration = player.getDuration();
var current = player.getCurrentTime();
if((duration - current) <= 1) {
player.stopVideo();
}
}
}, 1000); //every second
I ran into an issue where for some reason the iframe player was stopping the video before the video's end, and so not triggering the ENDED event, and ran into this question while trying to find a solution for that. Since my approach can solve your problem as stated, here's what I did (I left the console.log() debug lines in to make it easier for someone else using this to play around with):
var player_timeout;
function onPlayerStateChange(event) {
if (event.data == YT.PlayerState.PLAYING) {
console.log("PLAY [" + event.data + "]");
timeout_set();
}
if (event.data == YT.PlayerState.PAUSED) {
console.log("PAUSED [" + event.data + "]");
clearTimeout(player_timeout);
}
}
function timeout_func() {
console.log("timeout_func");
player.stopVideo(); // or whatever other thing you want to do 1 second before the end of the video
}
function timeout_set() {
console.log("timeout_set");
var almostEnd_ms = (player.getDuration() - player.getCurrentTime() - 1) * 1000;
console.log("almostEnd_ms: " + almostEnd_ms);
console.log("player.getCurrentTime(): " + player.getCurrentTime());
player_timeout = setTimeout(timeout_func, almostEnd_ms);
}
I'm trying to disable dayclick from functioning when there is already an event at the time. Is this possible? I've seen functions that stop people dragging one event to a conflicting time, but nothing that acts before creation.
Thanks
I've sorted it with click events function
function checkOverlap(event) {
var start = new Date(event);
var end = new Date(event.end);
var overlap = $('#calendar').fullCalendar('clientEvents', function(ev) {
if( ev == event) {
return false;
}
var estart = new Date(ev.start);
var eend = new Date(ev.end);
return (Math.round(estart) == Math.round(start));
});
if (overlap.length){
return false;
} else {
return true;
}
}
This is mostly possible because my app only allows users to make appointments for 1 hour and always on the hour. If you have a more flexible model where you can have variable length and starting time of the appointments, you will have to fiddle with the following line:
return (Math.round(estart) == Math.round(start));
I'm trying to build a streaming .mp3 player to run various sound files on my web site. To do that, I followed a tutorial that includes a code template at:
http://blog.0tutor.com/post.aspx?id=202&title=Mp3%20player%20with%20volume%20slider%20using%20Actionscript%203
However, whether I preserve the template's direction to the author's own sound file or insert my own direction to my online sound file, I keep on running into glitches in the ActionScript that I can't fathom.
Those errors are:
1084: Syntax error: expecting rightparen before _.
1086: Syntax error: expecting semicolon before rightparen.
When I try to correct them, I get new errors. I can't determine whether the sound file is loading; it certainly never plays. The volume slider does not work.
I did find one line that looked like it should have been commented out, the one that reads
to start at the same place
So I tried commenting that out. No dice. Same errors.
Thanks in advance for any suggestions. Code follows:
var musicPiece:Sound = new Sound(new URLRequest _
("http://blog.0tutor.com/JeffWofford_Trouble.mp3"));
var mySoundChannel:SoundChannel;
var isPlaying:Boolean = false;
to start at the same place
var pos:Number = 0;
play_btn.addEventListener(MouseEvent.CLICK, play_);
function play_(event:Event):void {
if (!isPlaying) {
mySoundChannel = musicPiece.play(pos);
isPlaying = true;
}
}
pause_btn.addEventListener(MouseEvent.CLICK, pause_);
function pause_(event:Event):void {
if (isPlaying) {
pos = mySoundChannel.position;
mySoundChannel.stop();
isPlaying = false;
}
}
stop_btn.addEventListener(MouseEvent.CLICK, stop_);
function stop_(event:Event):void {
if (mySoundChannel != null) {
mySoundChannel.stop();
pos = 0;
isPlaying = false;
}
}
var rectangle:Rectangle = new Rectangle(0,0,100,0);
var dragging:Boolean = false;
volume_mc.mySlider_mc.addEventListener(MouseEvent.MOUSE_DOWN, startDragging);
function startDragging(event:Event):void {
volume_mc.mySlider_mc.startDrag(false,rectangle);
dragging = true;
volume_mc.mySlider_mc.addEventListener(Event.ENTER_FRAME, adjustVolume);
}
function adjustVolume(event:Event):void {
var myVol:Number = volume_mc.mySlider_mc.x / 100;
var mySoundTransform:SoundTransform = new SoundTransform(myVol);
if (mySoundChannel != null) {
mySoundChannel.soundTransform = mySoundTransform;
}
}
stage.addEventListener(MouseEvent.MOUSE_UP, stopDragging);
function stopDragging(event:Event):void {
if (dragging) {
dragging = false;
volume_mc.mySlider_mc.stopDrag();
}
}
Syntax errors are just what it says they are, the code is not properly written. For instance , you shouldn't have an underscore after URLREquest
var musicPiece:Sound =
new Sound(new URLRequest("http://blog.0tutor.com/JeffWofford_Trouble.mp3"));
to start at the same place should be commented out, simply because it's a comment, it's not a variable or a function.
to call a function "play_" is not really good practice either. Call it soundPlay, if you're concern about conflicts.
same comment for pause_ and stop_
I wrote a program that gets youtube video URL and downloads it
Up today I did this:
1. get video "token" from "/get_video_info?video_id=ID" like:
http://www.youtube.com/get_video_info?video_id=jN0nWjvzeNc
2. Download Video by requesting it from "/get_video?video_id=ID&t=TOKEN&fmt=FORMAT_ID" like:
http://www.youtube.com/get_video?video_id=jN0nWjvzeNc&t=vjVQa1PpcFMgAK0HB1VRbinpVOwm29eGugPh3fBi6Dg%3D&fmt=18
But this doesn't work anymore!
What is the new download URL?
Thanks
Actually I'm working on the similar project that downloading the video file from youtube. I find that the get_video might be blocked by Youtube. so instead of using get_video., I use the video info retrieved from get_video_info and extract it to get the video file url.
Within the get_video_info, there are url_encoded_fmt_stream_map. After encoding it, you can find url and signature value of every video with different format. So the file url is like [url value]+'&signature='+[sig value].
Additionally I find the following topic that using same method with mine. Hope it can help you.
Can't Download from youtube
If you are interested about how to downloading youtube video file, there is a small program written by me to demonstrate the process. You are free to use it.
https://github.com/johnny0614/YoutubeVideoDownload
Add &asv=2 to the end of the URL.
You can get the stream directly by using only
http://www.youtube.com/get_video_info?video_id=jN0nWjvzeNc
I made a little script to stream youtube videos in PHP. See how the script get the video file.
<?php
#set_time_limit(0);
$id = $_GET['id']; //The youtube video ID
$type = $_GET['type']; //the MIME type of the video
parse_str(file_get_contents('http://www.youtube.com/get_video_info?video_id='.$id),$info);
$streams = explode(',',$info['url_encoded_fmt_stream_map']);
foreach($streams as $stream){
parse_str($stream,$real_stream);
$stype = $real_stream['type'];
if(strpos($real_stream['type'],';') !== false){
$tmp = explode(';',$real_stream['type']);
$stype = $tmp[0];
unset($tmp);
}
if($stype == $type && ($real_stream['quality'] == 'large' || $real_stream['quality'] == 'medium' || $real_stream['quality'] == 'small')){
header('Content-type: '.$stype);
header('Transfer-encoding: chunked');
#readfile($real_stream['url'].'&signature='.$real_stream['sig']); //Change here to do other things such as save the file to the filesystem etc.
ob_flush();
flush();
break;
}
}
?>
See the working demo here. I hope this can help you.
After a lot of failed tries, this github repositories help me:
https://github.com/rg3/youtube-dl
Get the url only like:
youtube-dl 'https://www.youtube.com/watch?v=bo_efYhYU2A' --get-url
download an mp4 and save as a.mp4 like:
youtube-dl 'https://www.youtube.com/watch?v=bo_efYhYU2A' -f mp4 -o a.mp4
Good luck.
Last time I was working on fixing one of the broken Chrome extensions to download YouTube video. I fixed it by altering the script part.
(Javascript)
var links = new String();
var downlink = new String();
var has22 = new Boolean();
has22 = false;
var Marked = false;
var FMT_DATA = fmt_url_map;//This is html text that you have to grab. In case of extension it was readily available through:document.getElementsByTagName('script');
var StrSplitter1 = '%2C', StrSplitter2 = '%26', StrSplitter3 = '%3D';
if (FMT_DATA.indexOf(',') > -1) { //Found ,
StrSplitter1 = ',';
StrSplitter2 = (FMT_DATA.indexOf('&') > -1) ? '&' : '\\u0026';
StrSplitter3 = '=';
}
var videoURL = new Array();
var FMT_DATA_PACKET = new Array();
var FMT_DATA_PACKET = FMT_DATA.split(StrSplitter1);
for (var i = 0; i < FMT_DATA_PACKET.length; i++) {
var FMT_DATA_FRAME = FMT_DATA_PACKET[i].split(StrSplitter2);
var FMT_DATA_DUEO = new Array();
for (var j = 0; j < FMT_DATA_FRAME.length; j++) {
var pair = FMT_DATA_FRAME[j].split(StrSplitter3);
if (pair.length == 2) {
FMT_DATA_DUEO[pair[0]] = pair[1];
}
}
var url = (FMT_DATA_DUEO['url']) ? FMT_DATA_DUEO['url'] : null;
if (url == null) continue;
url = unescape(unescape(url)).replace(/\\\//g, '/').replace(/\\u0026/g, '&');
var itag = (FMT_DATA_DUEO['itag']) ? FMT_DATA_DUEO['itag'] : null;
var itag = (FMT_DATA_DUEO['itag']) ? FMT_DATA_DUEO['itag'] : null;
if (itag == null) continue;
var signature = (FMT_DATA_DUEO['sig']) ? FMT_DATA_DUEO['sig'] : null;
if (signature != null) {
url = url + "&signature=" + signature;
}
if (url.toLowerCase().indexOf('http') == 0) { // validate URL
if (itag == '5') {
links += '<span class="yt-uix-button-menu-item" id="v240p">FLV (240p)</span>';
}
if (itag == '18') {
links += '<span class="yt-uix-button-menu-item" id="v360p">MP4 (360p)</span>';
}
if (itag == '35') {
links += '<span class="yt-uix-button-menu-item" id="v480p">FLV (480p)</span>';
}
if (itag == '22') {
links += '<span class="yt-uix-button-menu-item" id="v720p">MP4 HD (720p)</span>';
}
if (itag == '37') {
links += ' <span class="yt-uix-button-menu-item" id="v1080p">MP4 HD (1080p)</span>';
}
if (itag == '38') {
links += '<span class="yt-uix-button-menu-item" id="v4k">MP4 HD (4K)</span>';
}
FavVideo();
videoURL[itag] = url;
console.log(itag);
}
}
You can get separate video link from videoURL[itag] array.
The extension can be downloaded from here.
I hope this would help someone. This is working solution (as of 06-Apr-2013)