Skip to content Skip to sidebar Skip to footer

Using File System As Source Of Videos For Playing Offline

I am trying to add offline functionality to my HTML5 video player. I am attempting to write the files into the chrome file system as a blob and then read them from there. I believe

Solution 1:

filesystem: protocol stores files with reference to same origin as document which requests LocalFileSystem. That is, if JavaScript at Question is created at, for example, http://example.org, the path to LocalFileSystem should be same origin as http://example.org, not file: protocol.

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

Visit the local .html file once while online to get files and populate LocalFileSystem. If navigator.onLine is true, navigate to http://example.org, else get and process files and folders stored at LocalFileSystem.

Create a list as JSON or JavaScript Array to store list of files to fetch, instead of parsing an .htmldocument for file locations.

Store local file as a bookmark. Launch Chromium, Chrome with --allow-file-access-from-files flag set to access filesystem: protocol from file: protocol and file: protocol at filesystem: protocol, if not online.

<!DOCTYPE html><html><head><title>LocalFileSystem Offline Videos Bookmark</title></head><body><script>// location to visit if onlineconst onLineURL = "https://lorempixel.com/" 
                  + window.innerWidth 
                  + "/" 
                  + window.innerHeight + "/cats";

const props = {
  requestedBytes: 1024 * 1024 * 20000,
  folder: "videos",
  // list of files to fetch for offline viewingmediaList: [
    "http://mirrors.creativecommons.org/movingimages/webm/"
    + "ScienceCommonsJesseDylan_240p.webm"
  , "https://nickdesaulniers.github.io/netfix/demo/frag_bunny.mp4"
  ]
};

let grantedBytes = 0;

functiongetLocalFileSystem ({requestedBytes = 0, mediaList=[], folder = ""}) {
    if (!requestedBytes || !mediaList.length || !folder) {
      thrownewError("requestedBytes: Number"
                     + " or mediaList: Array"
                     + " or folder: String not defined");
    };
    // do stuff with `filesystem:` URLfunctionprocessLocalFilePath(localPath) {
        const video = document.createElement("video");
        document.body.appendChild(video);
        video.controls = true;
        video.src = localPath;
    }

    functionerrorHandler(err) {
        console.log(err);
    }

    functionwriteFile(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 writtenconsole.log(e.type, localPath + " written");
                    window.webkitResolveLocalFileSystemURL(localPath
                    , function(file) {
                        // file exists in LocalFileSystemprocessLocalFilePath(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 LocalFileSystemconsole.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 could be to utilize ServiceWorker

Solution 2:

Your user must grant your app permission to store data locally before your app can use persistent storage. That's why you have to request quota first. The amount of bytes you ask for 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 you are writing this for Chrome, here's how you manage the quota in Chrome

Post a Comment for "Using File System As Source Of Videos For Playing Offline"