A service worker that buffers a full video, so when the video tag ask for ranges, these can be satisfied. Play + pause = buffer the whole video.

Overview

Full Video Buffer with Service Workers

The specification of the preload attribute on a Video element won't allow you to fully buffer a video. This repo solves that.

Furthermore, browser heuristics make it so you only buffer what you will "probably" see from a video. Presumably, this is to save bandwidth for the most common case. Browsers won't buffer longer than a few seconds from your cursor position.

The main problem is that pause won't fill the buffer till the end. It will stop buffering near where your cursor is. This is an elegant solution for high-speed connections. The issue arises when people have unstable, unreliable, or slow connections. This is usually the result of location or using hotspots. The default buffering behaviour that browsers provide, results in these unfavourable conditions being unable to watch a video on the video tag itself. It will just spin once in a while and forever till the end.

The workarounds of having to download a video to be able to watch it later, as most people with unreliable connections do, means that you lose all the features that such a tag provides. You cannot watch videos in sync with your friends, for example.

This solves this problem by using Service Workers. After you instruct the library to buffer a video, the Service Worker listens to fetch events and will satisfy the ranges requested whenever data is available. When the data is not available, the Service Worker lets the browser do its thing. This is done this way so the browser can display data/video as soon as possible.

So you can do the old-school pause a video to make it buffer for some minutes, and start watching while it's still downloading! Improving the experience for users with unreliable connections. A huge time saver.

How to use it?

In your website, instance the Service Worker and include the client code which will keep the video in memory to give the ranges to the Service Worker when a video needs data. The video is not kept in memory on the Service Worker, because they are restarted or terminated whenever the browser feels like. You just add a video tag with the same URL that you choose to buffer and the Service Worker will do the work.

<script type="text/javascript" src="/full-video-buffer-client.js"></script>
<script>
	navigator.serviceWorker
		.register('/full-video-buffer-service-worker.js')
		.then(registration => registration.update())
		.catch(console.log)

	// instance the client
	let bufferVideo = new BufferVideo()
	// start buffering a video
	// optionally you can use a callback to display info
	bufferVideo('http://example.net/video.mp4', function (buffer) {
		console.log('The video url is ' + buffer.url)
		console.log('The video size is ' + buffer.size)
		console.log('It downloaded a ' + (buffer.buffered | 0) + '% of the video')
		console.log('Has been downloading for ' + (buffer.elapsed | 0) + ' seconds')
		console.log('It needs ' + (buffer.remaining | 0) + '~ seconds to finish download')
		console.log('It has been downloading at ' + buffer.speed + 'mb/s')
		console.log('Is the download done? ' + (buffer.done ? 'YES' : 'Not yet'))
	})
</script>

On the Service Worker, edit the extensions of the videos that you want to fully buffer, and the URL umbrella on which these videos are.

// extensions to hook
let extensions = /\.mp4$/

// under which URL?
let under = /\/video\//

You can guess when you can start watching without having any spinning wheel with the following formula:

bufferVideo('http://example.net/video.mp4', function (buffer) {
	// can we start playing while the video buffers?
	let video = document.querySelector('video')
	let watchableTime = (video.duration / 100) * buffer.buffered
	let canWatch = buffer.remaining - watchableTime < watchableTime

	console.log('Can we play the video yet?', canWatch)
})

Inspiration

We have had this problem for years. One of our friends uses a hotspot, and discarding them as "your internet is not good enough", wasn't an acceptable solution. To work around the difficulty, a full buffer button was added. Which made us wait, till our friend had fully fetched the video. Time to watch was download time + video length. Completely unacceptable having to wait so much without options to "buffer while you watch". Looking for solutions, we entered a Chrome bug https://bugs.chromium.org/p/chromium/issues/detail?id=1290913 We didn't get the response we wanted and made us think harder on the concern. This led us to investigate the fetch listener of Service Workers, which thankfully just worked.

Authors

You might also like...

HLS, DASH, and future HTTP streaming protocols library for video.js

videojs-http-streaming (VHS) Play HLS, DASH, and future HTTP streaming protocols with video.js, even where they're not natively supported. Included in

Jan 5, 2023

Bluzelle is a smart, in-memory data store. It can be used as a cache or as a database.

SwarmDB ABOUT SWARMDB Bluzelle brings together the sharing economy and token economy. Bluzelle enables people to rent out their computer storage space

Dec 31, 2022

In how many ways can you print in the console 50 times?

In how many ways can you print in the console 50 times I was asked at an interview how to print in the console "Hello World" 50 times in as few lines

Oct 4, 2021

Welcome to the LEGO Games Repository, where you can enjoy anytime, anywhere. This is the 2021 KNU Advanced Web Programming team project.

Welcome to the LEGO Games Repository, where you can enjoy anytime, anywhere. This is the 2021 KNU Advanced Web Programming team project.

Welcome to LEGO git repository! Here are some useful information about LEGO service. 0. Docker image Link : https://hub.docker.com/r/leibniz21c/legoga

Jul 21, 2022

A Gmail Clone which built with ReactJS and Redux. You can sign in with your Google Account, compose a new e-mail and send realtime emails to the project.

Gmail Clone with ReactJS A Gmail Clone that you can sign in with your Google Account, compose a new e-mail and send realtime emails to the project. Cl

Nov 14, 2022

This API can be use to all developers to get location details of Sri Lanka 🇱🇰 including major cities, sub areas, districts and Provinces. ⛳️

This API can be use to all developers to get location details of Sri Lanka  🇱🇰 including major cities, sub areas, districts and Provinces. ⛳️

Location Data API - Sri Lanka Table of Contents Introduction Technologies Implemantations Hosting Use Cases Getting Started Project Setup Contributing

Jun 29, 2022

Basic Dapp showing how a React Dapp can connect to Cronos using MetaMask and Crypto.com Defi Wallet

cronos-dapp-basic Basic Dapp showing how a React Dapp can connect to Cronos using MetaMask and Crypto.com Defi Wallet You need to have node version 14

Dec 31, 2021

This is a boilerplate for Nodejs (Nestjs/typescript) that can be used to make http server application.

Hexagonal architecture Table of Contents Overview Code architecture source code Service build information Regular user Advanced user Deployment Helm K

Sep 13, 2022
Simple, buffered, line-by-line file reader with customizable buffer size.

simple-line-reader Simple, buffered, line-by-line file reader with customizable buffer size. Install npm install simple-line-reader yarn add simple-li

null 3 Jan 15, 2022
Same as sqlite-tag but without the native sqlite3 module dependency

sqlite-tag-spawned Social Media Photo by Tomas Kirvėla on Unsplash The same sqlite-tag ease but without the native sqlite3 dependency, aiming to repla

Andrea Giammarchi 17 Nov 20, 2022
A Full Stack Amazon Clone which created using ReactJS with full E-Commerce Functionality!!

Amazon Clone with ReactJS A small web app that tries to imitate the desktop web version of amazon site, you can add items to the basket, delete them,

Özge Coşkun Gürsucu 50 Oct 3, 2022
A template for WebSockets powered Cloudflare Worker project using graphql-ws

?? graphql-ws on Cloudflare Workers A template for WebSockets powered Cloudflare Worker project using graphql-ws. The worker serves the following rout

Denis Badurina 26 Dec 18, 2022
Jérome Coupé's Insults As A Service

JCIaas - Jérôme Coupé's Insults as a Service Jérôme Coupé is internationally recognized for his insults and colorful nicknames. This webservice is an

Julien Moreau 4 Nov 19, 2021
💼 Easy Apply, a job-hunting service

Motivation Easy Apply is a job search tool that improves upon the current job seeking process by allowing users to create a video introduction of them

Tien Thanh Le 3 Mar 20, 2022
A Node.js ORM for MySQL, SQLite, PostgreSQL, MongoDB, GitHub and serverless service like Deta, InspireCloud, CloudBase, LeanCloud.

Dittorm A Node.js ORM for MySQL, SQLite, PostgreSQL, MongoDB, GitHub and serverless service like Deta, InspireCloud, CloudBase, LeanCloud. Installatio

Waline 21 Dec 25, 2022
🚀 A robust, performance-focused and full-featured Redis client for Node.js.

A robust, performance-focused and full-featured Redis client for Node.js. Supports Redis >= 2.6.12 and (Node.js >= 6). Completely compatible with Redi

Zihua Li 11.6k Jan 8, 2023
Firebase Extension to automatically push Firestore documents to Typesense for full-text search with typo tolerance, faceting, and more

Firestore / Firebase Typesense Search Extension ⚡ ?? A Firebase extension to sync data from your Firestore collection to Typesense, to be able to do f

Typesense 101 Dec 28, 2022
A typesafe database ORM that exposes the full power of handwritten sql statements to the developer.

TORM A typesafe database ORM that exposes the full power of handwritten sql statements to the developer. import { torm, z } from 'https://deno.land/x/

Andrew Kaiser 15 Dec 22, 2022