使用文件系统作为离线播放视频的来源

时间:2017-06-30 15:04:29

标签: javascript google-chrome-os html5-filesystem

我正在尝试为我的HTML5视频播放器添加离线功能。我试图将文件作为blob写入chrome文件系统,然后从那里读取它们。我相信我遇到的问题是文件实际上并没有被写入,只是文件名。由于我的下面的代码目前已经构成,它仍然有效,但仍然只有它永久连接到互联网。我的目标是将文件下载到文件系统中的永久目录,然后在互联网断开时继续播放。

$(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();
            }
        }
    });
});

2 个答案:

答案 0 :(得分:1)

在您的应用使用永久存储之前,您的用户必须授予您的应用在本地存储数据的权限。 这就是你必须先要求配额的原因。您要求的字节数为200000 * 1024 * 1024字节。

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

MDN documentation

我注意到您正在为Chrome写这个,here's how you manage the quota in Chrome

答案 1 :(得分:1)

filesystem:协议存储的文件引用与请求document的{​​{1}}相同的来源。也就是说,如果问题的JavaScript是在LocalFileSystem处创建的,则http://example.org的路径应与LocalFileSystem的原点相同,而不是http://example.org协议。

如果您尝试存储文件或文件夹以便在file:协议下离线访问,则可以创建file:文档以用作模板书签。

在线访问本地.html文件一次以获取文件并填充.html。如果LocalFileSystemnavigator.onLine,请导航至true,否则获取并处理http://example.org处存储的文件和文件夹。

创建一个列表LocalFileSystem或JavaScript JSON,以存储要提取的文件列表,而不是为文件位置解析Array .html

将本地文件存储为书签。启动Chromium,Chrome,document标记设置为--allow-file-access-from-files协议访问filesystem:协议,file:协议file:协议,如果不在线。

filesystem:

另见

另一种方法可能是利用<!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.github.io/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>