kiwix / kiwix-js

Fully portable & lightweight ZIM reader in Javascript
https://www.kiwix.org/
GNU General Public License v3.0
310 stars 135 forks source link

Display video content of ZIM files #172

Closed mossroy closed 5 years ago

mossroy commented 8 years ago

They are currently not handled. It might cause difficulties because of their size, either in jQuery or ServiceWorker mode.

Jaifroid commented 5 years ago

As mentioned by @mossroy in #339, videos are now working in SW mode. I believe adding support for them in jQuery mode should be a matter of:

One issue is whether the video data are currently steamed to SW, or whether the engine is extracting the data and posting the entire byte array to the SW via postmessage. I think it's the latter, as I don't see anything that handles streaming in the backend, but I may be wrong. I assume we can't easily emulate streaming in jQuery mode, but we can extract the video BLOB.

@mossroy , can you think of anything else?

Jaifroid commented 5 years ago

It looks like we might be able to play "directly" the data steam in the Uint8Array using the MediaSource interface of the Media Source Extensions API. It allows you to replace the media source of an html5 video player with a JavaScript function, and in particular it accepts the output of the function as an array buffer, which should be perfect for us. It might save us the overhead of having to convert the entire data stream of a very large video file (potentially) into a blob.

I'm a bit out of my depth here, however... There is a code example on the msdn page, in which it looks like we might be able to substitute the fetchAB function with our own readBinaryFile function's output for the video source. I guess we just have to try it... There's a working demo of the code on that page here.

Jaifroid commented 5 years ago

I've created Support-video-in-the-ZIM-in-jQuery-mode to start work on this. The first commit changes the video player's source src to data-kiwixsrc, which gets rid of the message "This video format is unsupported". The idea is to add the media source using the MediaSource interface after the rest of the page has rendered (or possibly when the user clicks play).

Jaifroid commented 5 years ago

The Support-video-in-the-ZIM-in-jQuery-mode now has preliminary support for video in at least the following ZIM -- the only one I've tested it on because the download size is reasonable ;-) -- tedxgeneva-2014_fr_all_2015-03.zim. Attempting to use the MediaSource interface only worked on Firefox Quantum: I think the technology is too experimental. So I fell back to using a blob URL, but with a dataView on the array buffer. This works nicely in Edge, Firefox ESR, Firefox Quantum, and Chromium. It doesn't work in IE11, but IE11 doesn't have native support for the webm video format used in this ZIM. It seems it may be available with a plugin, but I haven't tried that.

The video works without needing JavaScript support (the branch is based on master), using the native html5 video widget. Seeking backward and forward in the video seems to work fine in all the browsers that can play the video.

To test with the above ZIM, since the branch doesn't support JavaScript, you need to find a talk using our search function. For example, you can type the letter C, and this talk should appear: Comment-distinguer-linfo-de-lintox-Pryska-Ducoeurjoly-TEDxGeneva/index.html. Launch the talk, wait for the widget to be ready (it's quite fast), and then press play.

TODO:

  1. The video tag in this ZIM has its source in a <source ... src="source.html"> tag that is a child of the video tag. In Edge, it is sufficient to replace the src of this source tag with a Blob URL pointing to the dataView of the array buffer for the video, but neither Firefox or Chromium could play the video in that case (they complained there was no source, and I tested with a simple Blob of the content, same result). So instead, I inserted the src into the parent video tag, and all browsers can play the video in that case. This of course could create a problem if there is more than one source. We need some code to handle that, but I'm not sure how to do it, given that everytning is async. EDIT: This is now fixed: it was simply a case of needing to issue the load() function on the parent element for FF and Chromium to pick up the inserted videos;

  2. We need to destroy the Blob when it's no-longer needed, but I assume that would have to be on page navigation, because we can't know when the user has stopped playing the video or is merely having a coffee break ;-) .... EDIT: According to the Chromium devtools, the media blob is destroyed when the article is unloaded in readiness for a new article, which is the right point. Therefore I believe we don't need to attach specific code to the video block or the page to do this.

Jaifroid commented 5 years ago

I shall list here, as I find them, pages from non-TEDx ZIMs that have videos, that can be used for testing.

Jaifroid commented 5 years ago

I've fixed TODO 1 above.

Video playing is now tested and working also in FFOS simulator (at least above TEDx ZIM). The only browser it doesn't work in now is IE, but at least no exception is thrown in the latter. IE may work with other media sources (i.e. not webm).

I've generalized the function, so it is now called insertMediaBlobsJQuery and in theory it should work in exactly the same way for audio as for video. I need to find some audio to test it with.

EDIT: Audio: in recent ZIMs that have video/audio content, the audio seems to be played via a <video> media player. A good example is "Música de Venezuela" in wikipedia_es_venezuela_2018-09.zim. The audio plays fine in Edge, Firefox and Chromium.

Jaifroid commented 5 years ago

I've checked that TODO 2 above does not need to be implemented.

I think the branch is pretty much ready for a PR.