-
Notifications
You must be signed in to change notification settings - Fork 1.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Allow seeking throughout video files #8844
Conversation
Confirmed: well-noted has already signed the Contributor License Agreement (see contributing.md) |
✅ Deploy Preview for tiddlywiki-previews ready!
To edit notification comments on pull requests, go to your Netlify site configuration. |
Confirmed: well-noted has already signed the Contributor License Agreement (see contributing.md) |
@well-noted would you please tell what changes are made to the video parser in this pull request that are relevant to an end user. I am interested in knowing because I have a video annotation system based on wikitext as mentioned in this talk tiddlywiki post and share demo |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think there is something conceptually wrong with this PR. Parsers should not manipulate the DOM. --
core/modules/parsers/videoparser.js
Outdated
} | ||
|
||
if ($tw.browser) { | ||
const processedVideos = new WeakMap(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Jermolene -- Do we allow WeakMap
ES6 (ES2015) and const
, async
and arrow => functions
?
core/modules/parsers/videoparser.js
Outdated
|
||
/*jslint node: true, browser: true */ | ||
/*global $tw: false */ | ||
"use strict"; | ||
|
||
var VideoParser = function(type,text,options) { | ||
var VideoParser = function (type, text, options) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no spaces between params
core/modules/parsers/videoparser.js
Outdated
@@ -6,29 +6,161 @@ module-type: parser | |||
The video parser parses a video tiddler into an embeddable HTML element | |||
|
|||
\*/ | |||
(function(){ | |||
(function () { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no spaces
core/modules/parsers/videoparser.js
Outdated
}, { passive: true }); | ||
|
||
// Cleanup | ||
const observer = new MutationObserver(function(mutations) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no const
no let
atm
core/modules/parsers/videoparser.js
Outdated
// Cleanup | ||
const observer = new MutationObserver(function(mutations) { | ||
mutations.forEach(function(mutation) { | ||
if ([...mutation.removedNodes].includes(video)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no spread atm
core/modules/parsers/videoparser.js
Outdated
|
||
// Cleanup | ||
const observer = new MutationObserver(function(mutations) { | ||
mutations.forEach(function(mutation) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We usually use $tw.utils.each()
core/modules/parsers/videoparser.js
Outdated
|
||
xhr.send(); | ||
|
||
video.addEventListener('loadedmetadata', async () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no async
atm
core/modules/parsers/videoparser.js
Outdated
if (processedVideos.has(video)) return; | ||
|
||
// Create loading overlay | ||
const overlay = document.createElement('div'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We do use double quotes "div"
for strings
core/modules/parsers/videoparser.js
Outdated
// Create loading overlay | ||
const overlay = document.createElement('div'); | ||
overlay.style.cssText = 'position:absolute;top:0;left:0;width:100%;height:100%;background:rgba(0,0,0,0.5);display:flex;align-items:center;justify-content:center;color:white;'; | ||
overlay.innerHTML = 'Loading 0%'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hmmm, innerHTML
-- I am not sure if a "parser" should modify the DOM structure. Ususally widgets need to be used to create the DOM
@well-noted do you have an example showing what functionality this adds? |
Having sat with this for some time, it does occur to me that some of these features are likely outside the realm of a "parser" and might be better suited for a widget. |
https://talk.tiddlywiki.org/t/playing-with-parsers/11518/9?u=well-noted |
Additional note, one will need to transclude the src tiddler into another tiddler for this to work, because if one is viewing the video within the src, then, when the timestamp updates, the src is temporarily interrupted -- if this were to merged, therefore, we would need to make additional changes so that, if the current tiddler is the source tiddler, it would not store timestamps. |
(function () { | ||
|
||
/*jslint node: true, browser: true */ | ||
/*global $tw: false */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
indentation problem. It is safe to remove the (function(){
wrapper. So your "prettyfier" does not create redundant indents.
Hi @well-noted thank you for this, and apologies for being late to engage thanks to the holidays. Firstly, this is an interesting and determined attempt to solve a significant problem, and bring considerable benefits to users. I have some questions and possible reservations about the approach of preloading the entire media file using XMLHttpRequest. (I first saw an earlier version of the code that was much simpler, and haven't been able to fully review the new code and so its possible these points no longer apply).
There are also a few issues with the implementation, most of which I think have already been discussed:
If we were to focus on core changes to enable this functionality to be safely shipped as a plugin, a possible approach would be to refactor the video and audio parsers so that they generate special Stepping back, the fundamental problem with offering users a reliable and consistently good experience for video playback is really quite fundamental: TiddlyWiki works on the basis that any part of the DOM tree can be destroyed and recreated at any time which is utterly at odds with the needs of stateful HTML elements such as In many cases, we can work around the problem by ensuring that all the required state is stored in the wiki and so if the element is destroyed it can be recreated with the same state. This is accomplished using a custom widget rather than the generic HTML element widget. For example, that is how the edit text widget doesn't lose content when the page is refreshed; a plain However, that technique isn't good enough for media playback. Humans are sensitive to very short glitches, particularly in audio. So at the back of my mind has been the idea of a separate media player JS component that renders the |
I was also thinking about "interrupt free" state. My first thought was to render the video/audio elements in the The next thought was: Let's open a new window for the video or audio file. -- This may be able to keep the window alive even if the tiddler is closed in the story river. (That's my personal favourite) Or the other way around: Let root handle the video-tag and create a new small window with the controls only. This would allow us to move the controls around. IMO that's handy for audio-only UI. Where the UI would be completely out of the way. |
Heard, I have actually been discussing with etardiff storing the values as statetiddlers, which I believe would remove most of the need for DOM manipulation.
Personally, this solution would not work for me unless the time-values could still be accessed from within the wiki (And, still not quite as elegant, to my mind) as having the media element as an overlay on the page that allows for closing the story tiddler, as the audioparser modifications I have made currently allow for. I believe it is core to the philosophy of tiddlywiki that all values should be able to be referenced and transcluded in any context.
Yes, I believe that, using this as a proof-of concept, this PR could be refactored into a plugin if it were possible to intercept the video rendering through the widget system. and agree that it has the benefits of maintaining backward compatibility, while also allowing for additional features that might be helpful options to end-users but would unnecessarily bloat the core. I am satisfied with this as a direction and am happy to begin proceeding in refactoring as a plugin, unless there is a more elegant core solution on the horizon? |
Hi @well-noted would you be interested in drafting a PR for this? Let me know if you need any more information beyond my comments above. |
@Jermolene, lmk if this would be appropriate. |
Parser which allows buffering and scrubbing through video files