-
Notifications
You must be signed in to change notification settings - Fork 73
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
Add support for EchoVideos from Echo360 as source #90
Conversation
@echo360-damyon Hi! I just wanted to let you know that I have been asked to review your pull request(s). I am going to use github's regular review features unless you prefer a different way. |
Thanks, that's fine with me. |
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.
Hi again!
Thanks for your contribution in the name of H5P Group. They asked me to do an initial check up, so I deployed your code, ran some real world tests and had a look at your code for obvious things that might need to be taken care of. Here are my observations, leading to a potential need for changes. I am also going to report my observations to H5P Group and they will ultimately need to decide what changes feel to be necessary.
Functional
I used the new code in two different scenarios: As subcontent in H5P.Column, which leaves controls to H5P.Video and as pseudo subcontent in H5P.Interactive Video which has its own set of controls, so H5P.Video does not need to provide any.
-
The player does not only show the video, but (depending on the display ratio) also displays a black margin around the video, a name in the upper left-hand corner and some video chooser in the upper right-hand corner. If you compare this to the other video handlers, e.g. for HTML (https://h5p.org/interactive-video) or YouTube, then you will notice that the video should take up the whole width (in most cases). Extra visual elements (such as the video name or extra controls) should be put in a layer on top of the video (to be shown/hidden at your pleasing, e.g. on hover). I am not aware whether H5P Group would accept the way videos appear in your case - still waiting on an answer from them.
-
Your handler does not support all of the features that H5P.Video offers to authors (and needs to ensure that every handler can be used in every context). Your handler will be passed a couple of parameters in the 2nd arguments of your constructor function:
- {boolean}
controls
: Iftrue
(default), then the handler should display controls to the user, typically play/pause, a seekbar, a time code, a volume control and a playbackrate control. Iffalse
, then those must not be present and then and only then the content type that instantiated H5P.Video is responsible for offering controls and then uses the handler functions to relay commands to the actual player. Your handler (which leads to the extra H5P sharing URL) does never have controls (unlike your "public" sharing URL). The user can only click on the video to play/pause it. - {boolean}
autoplay
: If true, the handler should try to auto play the video - which will of course cannot overcome a browser's media policies. Your handler does not handle that parameter and never plays automatically. - {boolean}
loop
: If true, the handler should restart the video once it ended. Your handler does not handle that parameter and never loops the video. - {boolean}
fit
: Seems to be supported. - {object}
poster
: Image that should be displayed instead of the video before it is played. Your handler doesn't support this, but I think it's not mandatory. - {object}[]
tracks
: If set, the handler should display the respective subtitle tracks in order to allow people with hearing disabilities to follow the video content. This one is probably optional, because the YouTube handler cannot support tracks. - {boolean}
disableRemotePlayback
: Iftrue
, the player is not allowed to have a remote playback UI. You're not handling this, but probably don't have to anyway. And this should be optional. - {boolean}
disableFullscreen
: Iftrue
and the player's controls allow the user to go to full screen, that very control should be disabled. Your H5P sharing URL doesn't show a full screen button, but your regular sharing URL does. So, if you implement the controls, you should add an option to disable the full screen button. - {boolean}
deactivateSound
: Iftrue
the video should be played muted and if the player's controls allow the user to unmute the video or change the volume, the respective controls should be disabled. So, if you implement the controls, you may want to take care of this. - {number}
startAt
: If set, the video should start at the given time in seconds. Your handler seems to take care of that, but I am not entirely sure about some details, see below.
-
If I try to play/pause the video by clicking on it, I sometimes need to click twice or even multiple times to see an effect. Using the handler's
play
function seems to work reliably though. -
There's a slight but noticeable delay before the player reacts to a click; not with the YouTube handler, for instance, which also deals with remotely hosted videos.
-
Resizing works fine, but one can see quite some flickering.
-
Resuming (restarting at the time code that the user left off) works fine in Interactive Video, but not when run in Column. I didn't try to locate the issue, but potentially handling the
options.startAt
value does not work as expected while in Interactive Video, the latter probably calls seek to achieve the same effect. -
Changing the playbackrate from within Interactive Video triggers some weird effects. The rate between the player and Interactive Video seems to get out of sync, the video suddenly stops, etc. Could be an
async
issue. -
When using the play button of Interactive Video or the handler's play function directly, the video will not play with audio and calling
unmute
also doesn't have an effect. Audio will only play if the user clicks on the video to play it.
Code
I left a couple of comments in the code. Nothing serious. Given that there's some functionality that will need changing, a 2nd round may be necessary though. We can cross that bridge when we get to it.
-
The H5P coding guidelines seems to not have been consulted (https://h5p.org/documentation/for-developers/coding-guidelines). Yes, I am aware that older code of H5P Group may not adhere to it fully :-) If you want some eslint configuration that should enable eslint to fix most of the things automatically: https://github.com/NDLANO/eslint-config-ndla-h5p/blob/master/.eslintrc.js
-
Using jQuery. This is something that you could not have known, but H5P Group is about to remove jQuery from H5P core and thus doesn't want newly added code to use it so it won't have to be migrated to vanilla JavaScript later on.
-
There are some unused variables/functions left in the code.
-
You're using arrow functions which is more then fine, but you are mixing in some traditional "function" functions as well. Those can be replaced if not really needed (the constructor and the self-invoking function would cause trouble though or require more work, those should be fine as is).
-
Please add some line breaks in between functions and maybe in some other places to help distinguish blocks of code when reading it.
-
A public function
isLoaded(): boolean
is missing, see comments. But again, this is not something that's really documented by H5P Group ... -
Some JSDoc nitpicking ;-)
Hope my comments help you!
scripts/echo360.js
Outdated
* @param {Object} l10n Localization strings | ||
*/ | ||
function EchoPlayer(sources, options, l10n) { | ||
const self = this; |
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.
Keeping track of this
by introducing self
(or similar) is not required when using arrow functions.
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 removed all references to self.
scripts/echo360.js
Outdated
* @private | ||
* @returns {Promise} Echo Player SDK object | ||
*/ | ||
const loadEchoPlayerSDK = 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.
This function does not seem to be used anywhere.
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.
Removed
scripts/echo360.js
Outdated
let ratio = 9/16; | ||
const LOADING_TIMEOUT_IN_SECONDS = 30; | ||
const id = `h5p-echo-${++numInstances}`; | ||
const $wrapper = $('<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.
Please do not use jQuery but vanilla JavaScript unless you're answering a call from H5P core that still expects it or if you get it from H5P core as a parameter, e.g. in the attach
function. H5P Group is about to remove jQuery from H5P core and wants to limit places throughout their code base that they have to touch to remove usage of it.
Not many uses of jQuery should remain here, and the jQuery object doesn't need to be passed down as $
in the self-evoking function wrapper, but it can be called as H5P.jQuery
directly.
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 removed all uses of JQuery except where it's passed in as a parameter to a method.
scripts/echo360.js
Outdated
let currentTextTrack; | ||
let currentTime = 0; | ||
let duration = 0; | ||
let isMuted = 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.
This should be a boolean.
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.
It is a boolean now.
scripts/echo360.js
Outdated
let currentTime = 0; | ||
let duration = 0; | ||
let isMuted = 0; | ||
let volume = 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.
The default volume should be 1.
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.
Changed.
scripts/echo360.js
Outdated
* | ||
* @public | ||
*/ | ||
self.play = 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.
Why async
? I don't think it will ever be called asynchronously.
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 removed the async
scripts/echo360.js
Outdated
}; | ||
/** | ||
* @public | ||
* @returns {Number} Video duration in seconds |
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.
Can also return undefined
.
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.
Updated the JSDoc.
isMuted = false; | ||
}; | ||
/** | ||
* Whether the video is muted. |
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.
Please use common "command" scheme for function descriptions, so here e.g. Determine whether ...
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 added better function descriptions / params and return types for all functions.
scripts/echo360.js
Outdated
self.getCaptionsTrack = () => { | ||
return currentTextTrack; | ||
}; | ||
self.on('resize', () => { |
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.
A public function isLoaded(): boolean
is missing. It's supposed to return true
if the player that the handler introduces is done loading (in your case when the loadingPromise
resolves) and false
otherwise.
I know, this is not documented anywhere - but you might have noticed some error message when using your code in InteractiveVideo without that 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.
I added isLoaded which resolves true when the promise is completed.
scripts/echo360.js
Outdated
const $wrapper = $('<div/>'); | ||
const $placeholder = $('<div/>', { | ||
id: id, | ||
html: `<div class="h5p-video-loading" style="height: 100%; min-height: 200px; display: block; z-index: 100;" aria-label="${l10n.loading}"></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.
Setting border: none;
seems advisable to get rid of the (potential) default border that a browser may put there.
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 added this style.
Thanks Oliver, Responses to the points listed as Functional:
This is because Echo 360 Videos can have multiple video tracks and the user can switch between them while they watch the recording. E.g. talking head and powerpoint slides.
I have added this to the query string in the iframe url - in future we can update the Echo360 to follow this option.
I have added this.
I have added this.
Echo Video has it's own media editor where the poster image can be set.
Echo Video has it's own system for handling captioning for media including paid for captioning by third party providers.
I have added this to the query string in the iframe url - in future we can update the Echo360 to follow this option.
I have added this to the query string in the iframe url - in future we can update the Echo360 to follow this option.
The handler performs a seek when the video is loaded if this option is present.
I'll investigate column mode in more detail today.
The timing sync of the playback rates is under active development at the moment and this is not specific to h5p.
I have addressed this by adding allow="fullscreen, autoplay" to the iframe which grants permissions to play the audio. |
With regards to the Column mode - when testing I noticed that the patch for echo-h5p-editor-php-library looks correct against the current version on master branch - but when used with an older version (e.g. on h5p.org directly) - it requires additional changes to load the video the same way as youtube does it. If you search for Youtube in the scripts/h5peditor-av.js file - you can see it has special handling if the source provider is youtube. If used against the older library - those checks will need to be repeated for EchoVideo. |
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.
@echo360-damyon Thanks for all the changes in the name of H5P Group. Just letting you know: I don't know yet if I will continue working on this review or of they're going to take over. Either way, someone should reach out to you soon.
fd8fd8e
to
261340b
Compare
0ead985
to
45e03c5
Compare
Use updated quality options
…logic PLT-2090: Update quality option mapping
numInstances is supposed to reflect the number of instances of the handler for a unique element id, so it cannot be an instance property
Would cause trouble downstream, e.g. in Interactive Video
@echo360-damyon I was asked by H5P Group to have a 2nd look. I think I found some issued that I decided to fix directly with a short comment per commit instead of leaving extra comments that take longer to write. Please find echo360-damyon#1. Apart from that, I think that it's your player that needs changing now. Unless you agreed on something else with H5P Group, I think you may want to check:
|
Fix 2nd code review issues
Hi @otacke, thanks for the review again. I have merged in your changes to the PR. Also any testing against our QA server would have been hard recently because our QA system is changed between development and release regression testing as needed. It has just been reset to the latest release and will be acceptable to test against for a short time (not determined - probably a few weeks). Here are responses to your further comments:
There is is minimal flickering while resizing - this can be addressed in future but is not in scope of this H5P change.
This was addressed and is to do with the iframe permissions. |
@echo360-damyon Thanks for getting back to me.
That's not up for me to decide, and I was not part of your discussions with H5P Group. I merely compared your solution to the four other handlers and those fill the whole Canvas. That's what users of H5P are used to. If that's something that's not reasonable on your end, then you probably either have discussed this with H5P Group already (that's why I mentioned "Unless you agreed on something else with H5P Group [...]"), or their UX team will probably reach out to you anyway if they have an issue with that.
Yup, seems to be working nicely now.
Still doesn't seem to work, but this seems in fact to be an issue with H5P.InteractiveBook/H5P.Column/H5P.Video.
Will let H5P Group know.
Will let H5P Group know. This is up to their UX team.
Will also let H5P Group know. Also, while checking again, I noticed that double clicking on the video toggles the full screen mode. Again, um to H5P Group. |
Use updated quality options
numInstances is supposed to reflect the number of instances of the handler for a unique element id, so it cannot be an instance property
Would cause trouble downstream, e.g. in Interactive Video
When the message event is "timeline", message.data.duration is `undefined`, the duration value which is used by `getDuration()`, too, would be overwritten and be `undefined` (bug there then), and here looping would not work.
document.featurePolicy is experimental (no support in Firefox/Safari). Prevent potential crash.
The parameter is passed as a float in seconds
At Echo360 (https://echo360.com) we have been asked by our customers to allow videos captured in our EchoVideo platform to be able to be included in H5P content. We have added these features in our test environment and they will be released generally at the end of the year.
For this to work in the same way as other supported video platforms it will require changes to both this repository as well as the H5P Editor php library. Our changes are modelled after the other video platforms.