My client asked me to provide 'download' option on their video, just like native apps, where the video can be saved but would only be accessible to the specific app.
I finally stumbled upon FileSystem API, which allows sandboxed storage where the website will be given a specific storage space (just like how a virtual disk works).
I started testing my luck with a small video file. Two links that helped me the most were HTML5 Rocks and StackOverflow
I created the following function that requests FileSystem API from the browser:
initFileSystem() {
//Possible ways to access filesystem
window.requestFileSystem =
window.requestFileSystem || window.webkitRequestFileSystem;
//Define maximum size to allocate (I set it to 500MB), Set callback and an error handler
window.requestFileSystem(
window.TEMPORARY,
500 * 1024 * 1024,
onInitFs,
errorHandler
);
function errorHandler(e) {
console.log("Error: " + e);
}
Then I created the following callback function that creates a video (getfile). I fetched the video using XHR and saved it as a blob using FileWriter.
//Callback function
function onInitFs(fs) {
_fs = fs;
saveVideo(fs);
}
function saveVideo(fs) {
//Creates file named video.mp4
fs.root.getFile(
"video.mp4",
{ create: true, exclusive: true },
//Writes file after fetching
function (fileEntry) {
fileEntry.createWriter(function (fileWriter) {
fetchResource(fileWriter);
}, errorHandler);
},
errorHandler
);
}
//Fetches video using XHR
function fetchResource(fileWriter) {
var xhr = new XMLHttpRequest();
xhr.responseType = "arraybuffer";
xhr.open("GET", "http://example:com/video.mp4", true);
//Convert Video To Blob
xhr.onload = function (e) {
if (this.status == 200) {
var bb = new Blob([this.response]);
fileWriter.write(bb);
} else {
console.log(this.status);
}
};
xhr.send();
}
Finally, I created an HTML5 video player and appended the video blob as URL.
<video id="ourVideo" controls=""></video>
Note: Create the same initFileSystem function for playing video
function onInitFs(fs) {
_fs = fs;
playVideo(fs);
}
function playVideo(fs) {
//Fetches file from filesystem
fs.root.getFile(
filename,
{},
function (fileEntry) {
console.log(fileEntry);
document.querySelector("#ourVideo").src=fileEntry.fullPath;
fileEntry.file(function (file) {
var reader = new FileReader();
reader.onloadend = function (e) {
document.querySelector("#ourVideo").play();
};
reader.readAsText(file);
}, errorHandler);
},
errorHandler
);
}
Here, fileEntry.fullPath
creates a filesystem url (filesystem:http://example:com/temporary/video.mp4
) to fetch video from FileSystem.
Unfortunately, FileSystem is only supported by a few Chromium based browsers (Edge, Chrome, Chrome for Android, Opera, Samsung Internet) and is no longer standardized by W3C.
I hope that chrome would keep it afloat and other browsers (Firefox, Safari) would implement the same or provide an alternative.
Top comments (0)