I'm trying to create an audio playlist with jPlayer that will preload the next song in the list for seamless transitions, but I'm having some trouble with the looping feature.
I've got my code set up here: http://jsfiddle.net/Mz74e/
It uses 2 different players in order to preload the clips. The graphic UI is just shown for debugging, since I don't plan on using it in my final setup.
The current setup seems to loop properly in Firefox 12 and the flash player, but doesn't in Google Chrome 18 (It just goes to the beginning of the clip and sits there)
If anyone can look at how I'm using it and either figure out a workaround of a better implementation, that would be great!
Turns out that the problem was not where I originally though it was.
This exact same code works fine if the audio file is statically served by the web server.
I found this code here for the rangeDownload function:
http://mobiforge.com/developing/story/content-delivery-mobile-devices
Using this, the files are distributed properly to be played by html5.
Related
I'm working on a project where several videos are added to the HTML dynamically by JavaScript when they're needed to play, sort of like a remotely-controlled presentation. The order the videos will need to play is unknown at the time of page load and each video is under four seconds. However, the videos are large and naturally need to appear seamless when moving from when to the next, but since the videos are so big and, in some cases, loaded through the Internet, loading usually isn't seamless.
The way I'm adding videos right now is something like this:
$("body").append("<video class='onscreen' autoplay><source src='"+c.video+"'></source></video>");
Where c.video is a relative path to the video source.
Is there any way to preload videos directly from JavaScript beforehand without adding to the HTML? If not, what would be the best way to add to the HTML without having the video visibly playing and allowing for it to be dynamically added later?
I've seen several similar questions on StackOverflow (like this one) but they're all concerned with adding the video and only playing it later, once loaded. I'm sure it's possible to adapt the code presented in those, but I'm not quite sure how to go about doing it, especially as I don't understand some of the concept (please feel free to expand on your answer a bit; I don't just want code snippets!).
If it effects things at all, this will, in the foreseeable future, only have to run on Firefox and the videos will likely all be OGV (though there may be exceptions).
Before you say it can't be done please take a look at my train of thought and entertain me.
I have read on stackoverflow that it can't be done and how to implement this using ffmpeg and other stuff on the server side which is great and simpleish enough to comprehend .. ive even used an extensiion to Video.js i found on github that makes this one step easier. But none the less what if I dont have a copy of the <video src=... > and I really dont care to get one?
I Do not want to use a server to do this Okay with that out of the way, I understand thanks to a post from Paul Irish that video playback is not a shared aspect of web-kit ports (the code which powers basically every browser ... minus chrome canary now using blink a webkit fork) This kinda makes sense why certain browsers only support certain video containers.
So for the sake of simplicity: I want to make this functionality only available on Chrome and only MPEG-4 AVC video containers, why can't this be done if some how I can actually view each frame of the video while its playedback?
additional note
So the generating of video thumbnails is possible using by drawing frames to a canvas, this will only be part of a final solution to my problem, I'm looking to do this each and everytime a video is viewed not store images on my server after a first playback is completed by a user. What I would like to eventually work up to is generating a thumbnail as the video is downloaded that can be viewed while a user uses a dragging scrollbar to ff/rw to a point in the video. So this will need to be done as frames of video come available, not once they have been rendered by the browser for user to view
One can actually feed in a video to the canvas, as seen here in HTML5Doctor. Basically, the line that does the magic is:
canvasContext.drawImage(videoElement,0,0,width,height);
Then you can run a timer that periodically retrieves the frames from the canvas. There are 2 options on this one
get raw pixel data
get the base64 encoded data
As for saving, send the data to the server to reconstruct an image using that data, and save to disk. I also suggest you size your canvas and video to the size you want your screenshots to be since the video-canvas transfer automatically manages scaling.
Of course, this is limited by the video formats that are supported by the browser. As well as support for canvas and video.
Generating thumbnails during first render? You'd run into problems with that since:
You can't generate all frames unless it's rendered on the video element.
Suppose you have generated thumbnails during first run and want to use them for further runs. Base64 data is very long, usually 3 times the file size if the image. Raw pixel data array is width x height x 4 in length. The most viable storage candidate is localStorage, which is just 5-10MB depending on the browser.
No way to cache the images generated into the browser cache (there could be a cache hack that I don't know using data-urls).
I suggest you do it on the server instead. It's too much burden and hassle to do in the client side.
I have just started using the audio elements buffered attribute. I have only tested it in google chrome (canary build). So far the data in the structure has been different from what the default audio interface displays.
I have made two jsfiddles for the two ways I have implemented it
The first is the way I would imagine it to work http://jsfiddle.net/VB7Z8/20/
The second the way it actually seems to work http://jsfiddle.net/VB7Z8/18/
To see what I mean go to each fiddle (making sure your cache is cleared so it has stuff to buffer) and seek to the right side of the player making sure to leave a gap for it to buffer. I would think that now if you go back to the hole in the middle that the audio would not play but in fact it has been buffered only the buffered object has not been updated.
I have tested it with all the events and I still get the same result. Have I done something wrong or is this a problem with google chrome? I realise this is still in a draft stage of the standard.
This appears to have been changed at some point in the chrome development and it now works as the standard explains
I am trying to create a feature where a user can change (back and forth) between multiple videos while maintaining a single consistent audio. Think of being able to watch a concert from multiple angles but listening to a single audio. The trouble I am having with this feature is that there can not be a lag between the changes in video or the audio will no longer sync with the videos (especially true after multiple changes).
I have tried two methods, both using html5 only (I would prefer not use flash although I will eventually have a fallback) that have not worked seamlessly, although depending on the browser and hardware, it can come very close.
Basic Methods:
Method 1: Preloading all videos and changing the video src path on each click using javascript
Method 2: Again preloading video and using multiple tags and changing between them using javascript on each click.
Is there anyway to get either of these two methods to work seamlessly without a gap? Should I be using a slight of hand trick, like playing both videos concurrently for a second before revealing the second and stoping the first? Can this just not be done with html5 players? Can it be done with flash?
I have seen this type of question a couple of times with both video and audio with no clear solution, but they were a couple of months old and I was hoping there is now a solution. Thanks for the help.
Worth adding that it is possible with the MediaSource API proposed by Google. This API allows you to feed arbitrary binary data to a single video element, thus if you have your video split into chunks you can fetch those chunks via XHR and append them to your video element, they'll be played without gaps.
Currently it's implemented only in Chrome and you need to enable Enable Media Source API on <video> elements in chrome:flags to use it. Also, only WebM container is currently supported.
Here is an article on HTML5Rocks that demonstrates how the API works: "Stream" video using the MediaSource API.
Another useful article that talks about chunked playlist: Segmenting WebM Video and the MediaSource API.
I hope this implementation gets adopted and gets wider media container support.
UPDATE JUN 2014 Browser support is slowly getting better: (thanks #Hugh Guiney for the tip)
Chrome Stable
FF 25+ has a flag media.mediasource.enabled [MDN]
IE 11+ on Windows 8.1 [MSDN]
Did you find a better way to do that?
I implemented a double-buffered playback using two video tags.
One is used for the current playback, and the second for preloading the next video.
When the video ends I "swap" the tags:
function visualSwap() {
video.volume = video2.volume;
video2.volume = 0;
video.style.width = '300px';
video2.style.width = '0px';
}
It has some non-deterministic behavior, so I am not 100% satisfied, but it's worth trying...
Changing the SRC tag is fast, but not gapless. I'm trying to find the best method for a media player I'm creating and preloading the next track and switching the src via "ended" leaves a gap of about 10-20ms, which may sound tiny, but it's enough to be noticable, especially with music.
I've just tested using a second audio element which fires off as soon as the first audio element ends via the event 'ended' and that incurred the same tiny gap.
Looks like (without using elaborate hacks) there isn't an simple(ish) way of achieving gapless playback, at least right now.
it is possible. you can check this out: http://evelyn-interactive.searchingforabby.com/ it's all done in html5. they are preloading all videos at the beginning and start them at the same time. didn t had time yet, to check how they re doing it exactly, but maybe it helps if you check their scripts via firebug
After many attempts, I did end up using something similar to Method 2. I found this site http://switchcam.com and basically copied their approach. I pre-buffered as the video start time approached and then auto-played as the videos starting point hit. I had the current videos playing simultaneously (in a little div - as a UI bonus) and users could toggle between the videos switching the "main screen view". Since all videos were playing at once, you could choose the audio and the gap didn't end up being an issue.
Unfortunately, I never ended up solving my problem exactly and I am not sure my solution has the best performance, but it works okay with a fast connection.
Thanks for everyones help!
For example, I want the page to play an audio file while at the same time have some bullets slide into view at just the right moment that said bullet is talked about in the audio file. A similar effect would also be used for closed captioning. When I say reliable I mean specifically that the timing will be consistent across many common platforms (browser/OS/CPU/etc) as well as consistent in different sessions on the same platform (they hit refresh, it works again just as it did before, etc).
NOTE: It's OK if the answer is 'NO', but please include at least a little quip about why that is.
Check out this animation, which synchronizes a 3D SVG effect to an audio file.
The technique is explained in a blog post at http://mrdoob.com/blog/page/3. Look for the one entitled "svg tag+audio tag = 3D waveform". The key is to create a table of volume values corresponding to the audio file.
You'll obviously have some work to do in studying this example and the Javascript it uses to adapt it to your scenario. And it will probably only work in browsers that support HTML5.
Given the current situation and HTML5 support, I would solve this using Flash.