Using the file system as a video source for offline playback

I am trying to add standalone functions to my HTML5 video player. I am trying to write files to the chrome file system as blob and then read them from there. I believe that I ran into a problem when the files are not actually written, just the file name. Since my code below is currently compiled, it works, although still only if it is constantly connected to the Internet. My goal is to upload files to a permanent directory in the file system, and then continue playing if the Internet is disconnected.

$(document).ready(function() { var dir = "http://www.kevmoe.com/networks/gsplayer/"; var fileextension = ".mp4"; var srcfiles = $.ajax({ //This will retrieve the contents of the folder if the folder is configured as 'browsable' url: dir, success: function(data) { //List all .mp4 file names in the page $(data).find("a:contains(" + fileextension + ")").each(function() { var filename = $(this).attr("href").replace(window.location.host, "").replace("http://", ""); $("#container").append("<div id='div1' class='video'><video id='video1' class='vidarray' preload='none' poster='bkg.png'><source src='" + filename + "' type='video/mp4'></video></div>"); async: false; window.requestFileSystem = window.requestFileSystem || window.webkitRequestFileSystem; window.requestFileSystem(window.PERSISTANT, 200000 * 1024 * 1024, initFS, errorHandler); function initFS(fs) { console.log('filesystem engaged'); // Just to check if everything is OK :) // place the functions you will learn bellow here function errorHandler(err) { var msg = 'An error occured: '; }; function createDir(rootDir, folders) { rootDir.getDirectory(folders[0], { create: true }, function(dirEntry) { if (folders.length) { createDir(dirEntry, folders.slice(1)); } }, errorHandler); }; createDir(fs.root, 'files/video/'.split('/')); fs.root.getDirectory('video', {}, function(dirEntry) { var dirReader = dirEntry.createReader(); dirReader.readEntries(function(entries) { for (var i = 0; i < entries.length; i++) { var entry = entries[i]; if (entry.isDirectory) { console.log('Directory: ' + entry.fullPath); } else if (entry.isFile) { console.log('File: ' + entry.fullPath); } } }, errorHandler); }, errorHandler); fs.root.getFile(filename, { create: true, exclusive: true }, function(fileEntry) { fileEntry.createWriter(function(fileWriter) { var blob = new Blob([data], { type: 'video/mp4' }); fileWriter.write(blob); }, errorHandler); console.log('file downloaded'); }, errorHandler); //Try to add an event listener for when all files are finished loading into file system. Then use another function to source the videos locally. var dirReader = fs.root.createReader(); var entries = []; // Call the reader.readEntries() until no more results are returned. dirReader.readEntries(function(results) { //List all .mp4 file names in the page $(results).find("a:contains(" + fileextension + ")").each(function() { var filename = $(this).attr("href").replace(window.location.host, "").replace("http://", ""); $("#container").append("<div id='div1' class='video'><video id='video1' class='vidarray' preload='none' poster='bkg.png'><source src='" + filename + "' type='video/mp4'></video></div>"); async: false; }, errorHandler); }); }; function errorHandler() { console.log('An error occured'); }; }); var videos = $('.video'); //handle ending of video videos.find('video').on('ended', function() { playNextVideo(videos); }); // start with the first one playNextVideo(videos); function playNextVideo(videoList) { var activeVideo = videoList.filter('.active').removeClass('active'), // identify active video and remove active class activeIndex = videoList.index(activeVideo), // get the active video index in the group nextVideo = videoList.eq(activeIndex + 1), // get the next video in line actualVideo; // if there is no next video start from first if (nextVideo.length == 0) nextVideo = videoList.first(); // pause all videos videoList.find('video').each(function() { this.pause(); }) // get reference to next video element actualVideo = nextVideo.find('video').get(0); // add active class to next video nextVideo.addClass('active'); // load and play actualVideo.volume = 0.04; actualVideo.load(); actualVideo.play(); } } }); }); 
+5
source share
2 answers
Protocol

filesystem: stores files with a link to the same source as the document requested by LocalFileSystem . That is, if JavaScript is created in the question, for example, at http://example.org , the path to LocalFileSystem must match the protocol http://example.org , and not file:

If you are trying to save files or folders for accessing the file: protocol offline, you can create an .html document for use as a bookmark template.

Visit the local .html file once on the Internet to get the files and populate the LocalFileSystem . If navigator.onLine is true , go to http://example.org , otherwise get and process the files and folders stored in LocalFileSystem .

Create the list as JSON or JavaScript Array to save the list of files to extract, instead of parsing the .html document to place the files.

Store the local file as a bookmark. Launch Chromium, Chrome with the flag --allow-file-access-from-files set to access the filesystem: protocol from the file: protocol and the file: protocol in the filesystem: protocol if it is not on the network.

 <!DOCTYPE html> <html> <head> <title>LocalFileSystem Offline Videos Bookmark</title> </head> <body> <script> // location to visit if online const onLineURL = "https://lorempixel.com/" + window.innerWidth + "/" + window.innerHeight + "/cats"; const props = { requestedBytes: 1024 * 1024 * 20000, folder: "videos", // list of files to fetch for offline viewing mediaList: [ "http://mirrors.creativecommons.org/movingimages/webm/" + "ScienceCommonsJesseDylan_240p.webm" , "https://nickdesaulniers.imtqy.com/netfix/demo/frag_bunny.mp4" ] }; let grantedBytes = 0; function getLocalFileSystem ({requestedBytes = 0, mediaList=[], folder = ""}) { if (!requestedBytes || !mediaList.length || !folder) { throw new Error("requestedBytes: Number" + " or mediaList: Array" + " or folder: String not defined"); }; // do stuff with `filesystem:` URL function processLocalFilePath(localPath) { const video = document.createElement("video"); document.body.appendChild(video); video.controls = true; video.src = localPath; } function errorHandler(err) { console.log(err); } function writeFile(dir, fn, fp, localPath) { console.log(dir, fn, fp, localPath); dir.getFile(fn, {}, function(fileEntry) { fileEntry.createWriter(function(fileWriter) { fileWriter.onwriteend = function(e) { // do stuff when file is written console.log(e.type, localPath + " written"); window.webkitResolveLocalFileSystemURL(localPath , function(file) { // file exists in LocalFileSystem processLocalFilePath(localPath); }, errorHandler) }; fileWriter.onerror = errorHandler; fetch(fp).then(function(response) { return response.blob() }).then(function(blob) { fileWriter.write(blob); }).catch(errorHandler) }, errorHandler); }, errorHandler); } if (mediaList && mediaList.length) { navigator.webkitTemporaryStorage.requestQuota(requestedBytes , function(grantedBytes_) { grantedBytes = grantedBytes_; console.log("Requested bytes:", requestedBytes , "Granted bytes:", grantedBytes); window.webkitRequestFileSystem(window.TEMPORARY , grantedBytes , function(fs) { const url = fs.root.toURL(); mediaList.forEach(function(filename) { const localPath = url + folder + "/" + filename.split("/").pop(); window.webkitResolveLocalFileSystemURL(localPath , function(file) { // file exists in LocalFileSystem console.log(localPath + " exists at LocalFileSystem"); processLocalFilePath(localPath) }, function(err) { console.log(err, localPath + " not found in LocalFileSystem"); // Exception is thrown if file // or folder path not found // create `folder` directory, get files fs.root.getDirectory(folder, {} , function(dir) { writeFile(dir , filename.split("/").pop() , filename , localPath); }), errorHandler }) }) }) }, errorHandler) } } if (location.href !== onLineURL && navigator.onLine) { location.href = onLineURL; } else { getLocalFileSystem(props); } </script> </body> </html> 

see also


An alternative approach might be to use ServiceWorker

+1
source

The user must grant your application permission to store data locally before your application can use persistent storage. This is why you should first request a quota. The number of bytes you request is 200000 * 1024 * 1024 bytes.

 window.storageInfo.requestQuota(PERSISTENT, 200000 * 1024 * 1024, function(grantedBytes) { window.requestFileSystem(window.PERSISTENT, grantedBytes, onInitFs, errorHandler); }, errorHandler ); 

MDN Documentation

I noticed that you are writing this for Chrome, here is how you control the quota in Chrome

+1
source

Source: https://habr.com/ru/post/1269372/


All Articles