使用文件系统作为离线播放视频的来源 [英] Using File System as source of videos for playing offline
问题描述
我正在尝试为我的HTML5视频播放器添加离线功能。我试图将文件作为blob写入chrome文件系统,然后从那里读取它们。我相信我遇到的问题是文件实际上并没有被写入,只是文件名。由于我的下面的代码目前已经构成,它仍然有效,但仍然只有它永久连接到互联网。我的目标是将文件下载到文件系统中的永久目录,然后在互联网断开时继续播放。
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 that I am running into an issue where the files are not actually being written, just the file name. As my below code is currently constituted, it works, though still only if it is permanently connected to the internet. My goal is to have the files download to a persistent directory in the filesystem and then continue to play 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();
}
}
});
});
推荐答案
filesystem:
协议存储文件,引用与文档
相同的来源,请求 LocalFileSystem
。也就是说,如果在Question处创建JavaScript,例如 http://example.org
,则 LocalFileSystem $ c $的路径c>应与
http://example.org
相同,而不是文件:
协议。
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.
如果您尝试存储文件或文件夹以便访问文件:
协议,离线,您可以创建一个 .html
用作模板书签的文档。
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.
访问本地 .html
在线获取文件一次以获取文件并填充 LocalFileSystem
。如果 navigator.onLine
是 true
,请导航至 http://example.org
,否则获取并处理存储在 LocalFileSystem
的文件和文件夹。
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
.
创建列表为 JSON
或JavaScript Array
用于存储要获取的文件列表,而不是解析 .html
文件
用于文件位置。
Create a list as JSON
or JavaScript Array
to store list of files to fetch, instead of parsing an .html
document
for file locations.
将本地文件存储为书签。使用启动Chromium,Chrome - 允许文件访问文件
标记设置为访问 filesystem:
协议来自文件:
协议和文件:
协议在 filesystem:
协议,如果不在线。
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 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>
参见
-
如何在file:protocol 上使用webkitRequestFileSystem
How to use webkitRequestFileSystem at file: protocol
另一种方法可能是使用 ServiceWorker
An alternative approach could be to utilize ServiceWorker
这篇关于使用文件系统作为离线播放视频的来源的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!