Video dosen't play at all. [JavaScript] - javascript

Im trying to read a local file with videos. Here is the code. I used array to add the videos and play it in sequence but it didn't play any video.
var videos = new Array(); //("BigBuck.m4v","Video.mp4","BigBuck.m4v","Video2.mp4");
var currentVideo = 0;
function nextVideo() {
// get the element
videoElement = document.getElementById("play-video");
// remove the event listener, if there is one
videoElement.removeEventListener('ended', nextVideo, false);
// update the source with the currentVideo from the videos array
videoElement.src = videos[currentVideo];
// play the video
videoElement.play()
// increment the currentVideo, looping at the end of the array
currentVideo = (currentVideo + 1) % videos.length
// add an event listener so when the video ends it will call the nextVideo function again
videoElement.addEventListener('ended', nextVideo, false);
}
function yesnoCheck() {
document.getElementById("filepicker").style.display = 'none';
}
// add change event to pick up selected files
document.getElementById("filepicker").addEventListener("change", function (event) {
var files = event.target.files;
// loop through files
for (var i = 0; i < files.length; i++) {
// select the filename for any videos
if (files[i].type == "video/mp4") {
// add the filename to the array of videos
videos.push(files[i].name); // work from webkitRelativePath;
}
};
// once videos are loaded initialize and play the first one
nextVideo();
}, false);
Any suggestions? Thank you.

You're going to have to read the contents of the video, not just set the src to it's name. You can do so by using the FileReader.
I've adjusted your code, but I haven't tested it. Here's a working example on JsFiddle, though.
var videos = new Array(); //("BigBuck.m4v","Video.mp4","BigBuck.m4v","Video2.mp4");
var currentVideo = 0;
var reader = new FileReader();
// get th eelement
var videoElement = document.getElementById("play-video");
function nextVideo() {
// remove the event listener, if there is one
videoElement.removeEventListener('ended', nextVideo, false);
// read the file contents as a data URL
reader.readAsDataURL(videos[currentVideo]);
// increment the currentVideo, looping at the end of the array
currentVideo = (currentVideo + 1) % videos.length
// add an event listener so when the video ends it will call the nextVideo function again
videoElement.addEventListener('ended', nextVideo, false);
}
function yesnoCheck() {
document.getElementById("filepicker").style.display = 'none';
}
// add change event to pick up selected files
document.getElementById("filepicker").addEventListener("change", function (event) {
var files = event.target.files;
// loop through files
for (var i = 0; i < files.length; i++) {
// select the filename for any videos
if (files[i].type == "video/mp4") {
// add the whole file to the array
videos.push(files[i]);
}
};
// once videos are loaded initialize and play the first one
nextVideo();
}, false);
// once the file is fully read
reader.addEventListener('load', function() {
// you have the data URL in reader.result
videoElement.src = reader.result;
// play the video
videoElement.play()
});

Related

Problem streaming video using media source extensions

I seem to have a very strange problem. I am trying to play a video which is being streamed live using a web browser. For this, I am looking at the MediaSource object. I have got it in a way so that the video is taken from a server in chunks to be played. The problem is that the first chunk plays correctly then playback stops.
To make this even more strange, if I put the computer to sleep after starting streaming, then wake it up andthe video will play as expected.
Some Notes:
I am currently using chrome.
I have tried both of them ,with and without calling MediaSource's endOfStream.
var VF = 'video/webm; codecs="vp8,opus"';
var FC = 0;
alert(MediaSource.isTypeSupported(VF));
var url = window.URL || window.webkitURL;
var VSRC = new MediaSource();
var VURL = URL.createObjectURL(VSRC);
var bgi, idx = 1;
var str, rec, dat = [], datb, brl;
var sbx;
//connect the mediasource to the <video> elment first.
vid2.src = VURL;
VSRC.addEventListener("sourceopen", function () {
// alert(VSRC.readyState);
//Setup the source only once.
if (VSRC.sourceBuffers.length == 0) {
var sb = VSRC.addSourceBuffer(VF);
sb.mode = 'sequence';
sb.addEventListener("updateend", function () {
VSRC.endOfStream();
});
sbx = sb;
}
});
//This function will be called each time we get more chunks from the stream.
dataavailable = function (e) {
//video is appended to the sourcebuffer, but does not play in video element
//Unless the computer is put to sleep then awaken!?
sbx.appendBuffer(e.result);
FC += 1;
//These checks behave as expected.
len.innerHTML = "" + sbx.buffered.length + "|" + VSRC.duration;
CTS.innerHTML = FC;
};
You are making two big mistakes:
You can only call sbx.appendBuffer when sbx.updating property is false, otherwise appendBuffer will fail. So what you need to do in reality is have a queue of chunks, and add a chunk to the queue if sbx.updating is true:
if (sbx.updating || segmentsQueue.length > 0)
segmentsQueue.push(e.result);
else
sbx.appendBuffer(e.result);
Your code explicitly says to stop playing after the very first chunk:
sb.addEventListener("updateend", function () {
VSRC.endOfStream();
});
Here is what you really need to do:
sb.addEventListener("updateend", function () {
if (!sbx.updating && segmentsQueue.length > 0) {
sbx.appendBuffer(segmentsQueue.shift());
}
});

Audio Player JavaScript

I am trying to build an audio player. I can't seem to get to get the on load function to work. My songs are in E:\Music Player\Songs file directory path.
<script type=text/javascript>
var songs = ["Nobody Compares To You - Gryffin.mp3", "Crawl Outta Love - Illenium.mp3",
"Higher Ground - Odesza.mp3"
];
var poster = ["Nobody Compares to You - Gryffin.png", "Awake - Illenium.jpg",
"A Moment Apart - Odesza.jpg"
];
var songTitle = document.getElementById("songTitle");
var fillBar = document.getElementById("fill");
var song = new Audio();
var currentSong = 0; // it points to the current song
window.onload = playSong; // it will call the function playSong when window is load
function playSong() {
song.src = "./Songs/" + songs[currentSong]; //set the source of 0th song
songTitle.textContent = songs[currentSong]; // set the title of song
song.play(); // play the song
}
</script>
According to my knowledge, window.onload = playSong; is incorrectly calling playSong function.
window.onload = playSong(); // Brackets after a function name is mandatory.
Try this one.

get index of jquery element after event has fired

I'm creating video objects via jquery from an array of urls that point to mp4 files.
I want to have the first video autoplay then once its finished pick up on the "ended" function and play the next video in the sequence.
$(document).ready(function () {
var urls = ["https://s3-us-west-1.amazonaws.com/linkto.mp4", "https://s3-us-west-1.amazonaws.com/linktoother.mp4"]
var videos = [];
for (var i = 0; i < urls.length; i++) {
var path = urls[i];
var video = $('<video></video>');
var source = $('<source></source>');
source.attr('src', path);
source.appendTo(video);
if (i === 0) {
video.attr('autoplay', 'true');
}
video.attr('id', 'video_' + i);
video.attr('preload', 'true');
video.attr('width', '100%');
videos.push(video);
video.on('ended', function () {
console.log('Video has ended!' + i);
// playNext(video);
});
$('#movie').append(video);
}
I can see the movies generated and the first one plays fine. The problem is when 'ended' function the variable i == 2 because thats how many videos are in the array and the for loop increased i. I've been away from javascript for a while. I can think of workarounds like adding an index attribute to the video element or something but basically how do I get the correct index in the "ended" function.
The problem here is the wrong use of a closure variable in a loop.
In your case you can create a local closure by using $.each() to iterate over the array
$(document).ready(function () {
var urls = ["https://s3-us-west-1.amazonaws.com/linkto.mp4", "https://s3-us-west-1.amazonaws.com/linktoother.mp4"]
var videos = [];
$.each(urls, function (i, path) {
var video = $('<video></video>');
var source = $('<source></source>');
source.attr('src', path);
source.appendTo(video);
if (i === 0) {
video.attr('autoplay', 'true');
}
video.attr('id', 'video_' + i);
video.attr('preload', 'true');
video.attr('width', '100%');
videos.push(video);
video.on('ended', function () {
console.log(i)
});
$('#movie').append(video);
})
})
You really don't want to have the index, since all the video elements are siblings you can just find the next sibling of the currently ended video element
video.on('ended', function () {
console.log('Video has ended!' + $(this).index());
var $current = $(this),
$next = $this.next();
console.log($next.find('source').attr('src'))
//playNext($(this));
});
Creating closures in loops: A common mistake
JavaScript closure inside loops – simple practical example

Javascript object not setting image to an array

I am working on a HTML5 game and I have a function that should load an image and append it to an array for later displaying to a canvas. The code for the loading function is here...
function loadImage(url) {
box.images.total++;
image = new Image();
image.src = url;
image.onload = function () {
box.images.loaded++;
};
box.images[box.images.length] = image;
}
The code for the holding array is here...
var box = new Object({});
box.images = new Array([]);
And the rendering code is here...
loadImage("images/background.png");
while (box.images.loaded<box.images.total) {console.log("lol");}
box.ctx.drawImage(box.images[0], 0, 0);
My hope was that this would attempt to load the set of images and would increase the counter each time. Then when an image loads it would increase the loaded counter and then once all of the code has run the rest of the code would run. But I get an error saying "function was found that matched the signature provided" and the array appears to contain an empty element.
Also i'm in Chrome on Xubuntu 12.04
Update It turns out that the image was being put in index 1 not 0 and that was why the image wasn't loading. But it still doesn't render the image please help.
Another Update So it turns out that both total and loaded were NaN and so the while loop wasn't able to load at all. I set them to zero and the wile loop didn't terminate and it crashed my browser tab.
You need some sort of Promise or a callback function. For simplicity, I would suggest the callback. Example:
var box = {};
box.images = [];
box.images.total = box.images.loaded = 0;
function loadImage(url, callback) {
box.images.total++;
image = new Image();
image.onload = function () {
box.images.loaded++;
// We call something when the image has loaded
callback();
};
image.src = url;
box.images[box.images.length] = image;
}
function loadAllImages(urls, callback) {
// Loop through each image and load url
for (var i = 0; i < urls.length; ++i) {
var url = urls[i];
loadImage(url, function() {
// When everything loads, call callback
console.log(box.images.total, box.images.loaded);
if (box.images.loaded === box.images.total) callback();
});
}
}
window.onload = function() {
box.ctx = document.querySelector("canvas").getContext("2d");
loadAllImages([
"https://lh4.googleusercontent.com/-rNTjTbBztCY/AAAAAAAAAAI/AAAAAAAAAFM/RNwjnkgQ9eo/photo.jpg?sz=128",
"https://www.gravatar.com/avatar/20e068dd2ad8db5e1403ce6d8ac2ef99?s=128&d=identicon&r=PG&f=1"
], function() {
// Do whatever once everything has loaded
box.ctx.drawImage(box.images[0], 0, 0);
});
};
<canvas>
</canvas>

titanium start and stop sound

I have this working in Javascript but can't seem to get it working on Titanium.
Here is the code:
var index = 0;
var i = 0;
// Filename
var wordSoundArray = [];
wordSoundArray.push('audio/the.mp3');
wordSoundArray.push('audio/of.mp3');
wordSoundArray.push('audio/and.mp3');
wordSoundArray.push('audio/a.mp3');
wordSoundArray.push('audio/to.mp3');
wordSoundArray.push('audio/in.mp3');
wordSoundArray.push('audio/is.mp3');
wordSoundArray.push('audio/you.mp3');
wordSoundArray.push('audio/that.mp3');
wordSoundArray.push('audio/it.mp3');
wordSoundArray.push('audio/he.mp3');
wordSoundArray.push('audio/was.mp3');
wordSoundArray.push('audio/for.mp3');
wordSoundArray.push('audio/on.mp3');
wordSoundArray.push('audio/are.mp3');
newWordBtn.addEventListener("click", function(e){
wordLabel.text = newWordArray[i++];
if (i === newWordArray.length)
i = 0;
var snd = Titanium.Media.createSound({url:wordSoundArray[index++]});
if (index === wordSoundArray.length)
index = 0;
if (snd.isPlaying()) {
snd.stop();
snd.play();
} else {
snd.play();
}
});
When a user presses the button they get a new word and the sound that goes with that word. However, if the user presses the button before the sound is finished it simply starts the new sound and they overlap each other. That is where the snd.isPlaying portion of the code of the code comes in. I'm pretty sure my mistake is in there.
So you actually have dead code here:
var snd = Titanium.Media.createSound({url:wordSoundArray[index++]}));
...
// You just created the sound, so it will never be playing right off the bat
if (snd.isPlaying()) {
// This will never be called
snd.stop();
snd.play();
} else {
// This will happen every time the user clicks the button
snd.play();
}
I think its good practice to pre-load all your sound assets before you start execution, so maybe try replacing your wordSoundArray with entries of the form:
wordSoundArray.push(Titanium.Media.createSound({url:'audio/the.mp3'});
Once you have done this (all our sound assets are preloaded, this will be good for memory too) we can change the listener to something like this:
newWordBtn.addEventListener("click", function(e){
wordLabel.text = newWordArray[i++];
if (i === newWordArray.length)
i = 0;
// Instead of creating the sound, just fetch it!
var snd = wordSoundArray[index++];
if (index === wordSoundArray.length)
index = 0;
// Now this will work, but maybe you want to make sure all the sounds are off instead?
if (snd.isPlaying()) {
snd.stop();
snd.play();
} else {
snd.play();
}
});
Looking at your code though, it appears you want to stop the previous sound playing and then start the next one, so you would need to change the listener to this:
newWordBtn.addEventListener("click", function(e){
wordLabel.text = newWordArray[i++];
if (i === newWordArray.length)
i = 0;
// Stop the last sound from playing
if(index > 0) {
var lastSound = wordSoundArray[index-1];
lastSound.stop();
}
// Instead of creating the sound, just fetch it!
var nextSound = wordSoundArray[index++];
if (index === wordSoundArray.length)
index = 0;
// Play the next sound
nextSound.play();
});

Categories