Preloading HTML5 video keeps connection opened - spring

I am working in a web application that provides some (html5 compatible) videos to the user. I am using videojs to show those videos with the "preload" attribute set to "auto".
I am aware that browsers usually only load a portion of the video and that is ok for me. The problem is that it keeps the connection opened with the backend (spring-boot) that is dispatching the video by writing to the OutputStream:
while ((read = input.read(buffer)) > 0) {
output.write(buffer, 0, read); // once video is preloaded, it keeps waiting here
output.flush();
}
After 1 min, if the user doesn't hit the play button, it throws a ClientAbortedException: java.net.SocketTimeoutException.
Is there any way to make the browser close the connection once the preload has finished? (Note that for our system, it is important to close the InputStream as soon as possible if it is not being used).

Yes, I agree. This is an issue.
The sugestion below only will work if you are using playlist and segments, like HLS and DASH.
If you are playing static files (vod) and its segments are cached on the browser's cache, you can restart the player using a set timeout function and reload all settings again, replacing the preload attribute with "none", on the ready event. So, you can control the cache in seconds that you want.
var stopcache = true;
// when ready, cache segments by 5 seconds and restart player
player.on('ready',function(){
setTimeout(function() {
if (stopcache) {
stopcache = false; // avoid repeat
player.preload('none'); // or false if API allows
player.autoplay(false);
player.src('');
player.src({
type:'application/x-mpegURL',
src:'//example.com/hls/stream.m3u8'
});
}
}, 5000);
});
// avoid player reload if user played the file
player.on('play',function(){ stopcache = false; });
This is just a sugestion, I didn't try it but I believe that it will work because the playlist and segments are cached by the browser (vod). I use the same technique when playing live videos, reloading the url when user press play after pause, forcing the player starts from the actual live segment.

Related

Three.JS - AudioAnalyser() not working with audio source as Stream type in Safari

I'm developing a streaming radio in 3D using Three.JS, I'm sending music as a PeerConnection to my clients attaching a THREE.AudioAnalyser() to display 3D bars that move according to frequencies.
Sound is working great in all platforms, but THREE.AudioAnalyser() with an input source of stream type only works on Chrome, Safari is not working at all :frowning:
var listener = new THREE.AudioListener();
var audio = new THREE.Audio( listener );
audio.setMediaStreamSource( stream );
audioAnalyser = new THREE.AudioAnalyser( audio, 128 );
function loop(){
console.log(audioAnalyser.getFrequencyData());
}
The console.log() of the loop() function should contain an Array of Integers, on Chrome is all good, Safari logs [0,0,0,0,0,0,0,0]
What could be causing this issue? It seems to work everywhere but not on Safari, and also it only seems to fail when the source is a stream.
Not 100% sure, but you might want to connect the output of the AnalyserNode to the destination node. You may want to stick a GainNode with a gain of 0 in between, just in case you don't really want the audio from the AnalyserNode to be played out.

Xamarin Forms: How to switch images without "flicker"?

[I found this question asked once before on SO about a year ago on but it went unanswered so I am asking again (wasn't sure whether best practice was to create a new question or "bump" the existing one).]
I have a Xamarin Forms application which is receiving a stream of JPEGs over HTTP and I want to keep updating a single Image placeholder with their contents. The frame rate at which I receive the images is very slow by design (maybe 5 fps at most) as this is for a time-lapse photography project. I want to be able to show the stills as an animation (think: taking a photo of a plant once per hour and then "playing" all of the stills to create a lively animation of said plant).
The problem I am having is with "flicker" while swapping one image out for the next. I've tried a variety of approaches, including having two Images (one visible at a time) and only changing the visibility once I'm done loading the latest image (I think this is maybe a naive form of double-buffering?). Have also looked into Motion JPEG, HTTP Keep-Alive, and even using a WebView (I have a valid Motion JPEG endpoint that I can read from). Anyway, nothing that I've found so far has helped reduce the flicker and therefore the "animation" of the stills remains very "jerky" for lack of a better way to put it, with a momentary blank (white) pane between stills. Frankly speaking, it looks like crap.
Here is the gist of the code which fetches the next "frame" and updates the "player" image:
var url = $"{API_BASE_URL}/{SET_ID}/{_filenames[_currentFilenameIndex]}";
var imageBytes = await Task.Run(() => _httpClient.GetByteArrayAsync(url));
var imageBytesStream = new MemoryStream(imageBytes);
var timeComponents = _filenames[_currentFilenameIndex].Split('T')[1].Split('.')[0].Split('-');
var timeText = $"{timeComponents[0]}:{timeComponents[1]}:{timeComponents[2]}";
Device.BeginInvokeOnMainThread(
() =>
{
TimePlaceholder.Text = $"{timeText} (Image {_currentFilenameIndex + 1}/{_filenames.Count})";
ImagePlaceholder.Source = ImageSource.FromStream(() => imageBytesStream);
});
Any suggestions would be greatly appreciated.

How long does Image.prefetch actually cache the image?

When testing on the iOS Simulator I seem to be downloading the image every time the app is opened. Is this the intended behavior?
The three images are prefetched initially, and the cache is used whenever I reference that URI but as soon as I reload the app everything seems to reset.
Here are some snippets of how I'm using it inside my component.
prefetchImages(images) {
let p = [];
images.map((url) => {
p.push(Image.prefetch(url).then(() => {
console.log('image prefetched:', url);
}));
});
return Promise.all(p);
}
this.prefetchImages([
'http://domain.com/myimg1.jpg',
'http://domain.com/myimg2.jpg'
])).then((a) => {
console.log('all images have been prefetched');
});
I would just like to know whether or not the images are meant to be cached even after the app is relaunched.
Ideally I'd like to download some assets once and have them persist to disk for a sensible period.
Does Image.prefetch check HTTP Status Codes behind the scenes? I'm not sure how to log network requests through the simulator to see. I wonder if it receives a 304 Not Modified when the app is relaunched, or whether it's always 200. Any help appreciated.

Auto Play YouTube Video Without Slowing Down Page Load Time

I've had a scan through previous questions and can't seem to find anything about adding a YouTube video to a page and having it auto play without effecting page load speeds. Is there anyway to allow the full content of the page to carry on loading without the Video creating a bottle neck situation?
It will depend on the device and browser but on a laptop, using the HTML5 video mechanism your page will continue to load while the video starts on most OS's and browsers, without you having to do any complicated ordering.
The video is streamed, which in practice means small chunks are requested at a time, so there is no delay waiting for the full video to download. Most browsers will implement this playback in a way that does not interfere with the rest of the page download and display - e.g. in a separate thread, and even sometimes mostly in the device HW itself.
On a mobile device things are different - many mobile devices will not allow autoplay at all. They implement this restriction protect to the user from incurring excessive charges on mobile data plans.
Many mobile deices will also force the video to play full screen when it does play - this tends to be on a device by device basis. For example iPhones play videos full screen but larger iPad's will allow it inline in the web page (this is an ever changing playing field so its worth checking the status with the latest release if you are interested in a particular device).
Searching around on line I came across this little bit of javascript, and an amend to the YouTube embed code which helped.
<iframe width="854" height="480" src="" data-src="https://www.youtube.com/embed/ihhAswAsg8c?rel=0&autoplay=1" frameborder="0" allowfullscreen></iframe>
Notice how the src="" is empty and the url has been put inside a data-src="" instead. Then add the following javascript.
$(document).ready(function() {
function init() {
var vidDefer = document.getElementsByTagName('iframe');
for (var i=0; i<vidDefer.length; i++) {
if(vidDefer[i].getAttribute('data-src')) {
vidDefer[i].setAttribute('src',vidDefer[i].getAttribute('data-src'));
}
}
}
window.onload = init;
});
This will then stop the iframe from automatically making lots of http requests until the rest of the page has finished loading.

Flash & SWFObject2 stops flash audio in background tabs

I use SWFObject 2.2 to play sounds for an AJAX based game I have made. I used to use SWFObject 1, and everything worked fine, but when I updated my game, I updated to 2.2. Now, when users try to listen to music on Youtube or Pandora in another tab on Firefox while playing the game, they can't unless they have that tab selected.
What is interesting is that the video doesn't stop playing, just the sound stops working. I run the following javascript in order to stop the sound effect in my flash file, and it seems to stop the sound at the exact same time on Youtube or Pandora:
$('myflashid').doStop();
The following is the actionscript used for my flash file:
import flash.external.ExternalInterface;
snd=new Sound();
snd.attachSound("MySound1");
ExternalInterface.addCallback( "doPlay", this, doPlay );
ExternalInterface.addCallback( "doStop", this, doStop );
function doPlay() {
snd.start();
}
function doStop() {
snd.stop();
}
I am not sure why this fixes it, but if I set the volume to 0 instead of doing snd.stop(); and then set the volume back to 100 when I start it again, it seems to work fine.

Resources