Skip to content
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

Merged
merged 50 commits into from
May 3, 2024

Conversation

echo360-damyon
Copy link
Contributor

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.

@otacke
Copy link
Contributor

otacke commented Feb 13, 2024

@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.

@echo360-damyon
Copy link
Contributor Author

Thanks, that's fine with me.

Copy link
Contributor

@otacke otacke left a 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.

  1. 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.

  2. 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: If true (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. If false, 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: If true, 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: If true 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: If true 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.
  1. 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.

  2. 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.

  3. Resizing works fine, but one can see quite some flickering.

  4. 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.

  5. 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.

  6. 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.

  1. 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

  2. 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.

  3. There are some unused variables/functions left in the code.

  4. 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).

  5. Please add some line breaks in between functions and maybe in some other places to help distinguish blocks of code when reading it.

  6. A public function isLoaded(): boolean is missing, see comments. But again, this is not something that's really documented by H5P Group ...

  7. Some JSDoc nitpicking ;-)

Hope my comments help you!

* @param {Object} l10n Localization strings
*/
function EchoPlayer(sources, options, l10n) {
const self = this;
Copy link
Contributor

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.

Copy link
Contributor Author

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.

* @private
* @returns {Promise} Echo Player SDK object
*/
const loadEchoPlayerSDK = async () => {
Copy link
Contributor

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.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed

let ratio = 9/16;
const LOADING_TIMEOUT_IN_SECONDS = 30;
const id = `h5p-echo-${++numInstances}`;
const $wrapper = $('<div/>');
Copy link
Contributor

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.

Copy link
Contributor Author

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.

let currentTextTrack;
let currentTime = 0;
let duration = 0;
let isMuted = 0;
Copy link
Contributor

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.

Copy link
Contributor Author

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.

let currentTime = 0;
let duration = 0;
let isMuted = 0;
let volume = 0;
Copy link
Contributor

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.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed.

*
* @public
*/
self.play = async () => {
Copy link
Contributor

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.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I removed the async

};
/**
* @public
* @returns {Number} Video duration in seconds
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can also return undefined.

Copy link
Contributor Author

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.
Copy link
Contributor

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 ...

Copy link
Contributor Author

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.

self.getCaptionsTrack = () => {
return currentTextTrack;
};
self.on('resize', () => {
Copy link
Contributor

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.

Copy link
Contributor Author

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.

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>`
Copy link
Contributor

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.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added this style.

@echo360-damyon
Copy link
Contributor Author

Thanks Oliver,

Responses to the points listed as Functional:

  1. "video chooser in the upper right-hand corner"

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.

  1. Features / options

{boolean} controls:

I have added this to the query string in the iframe url - in future we can update the Echo360 to follow this option.

{boolean} autoplay:

I have added this.

{boolean} loop:

I have added this.

{object} poster:

Echo Video has it's own media editor where the poster image can be set.

{object}[] tracks:

Echo Video has it's own system for handling captioning for media including paid for captioning by third party providers.

{boolean} disableFullscreen:

I have added this to the query string in the iframe url - in future we can update the Echo360 to follow this option.

{boolean} deactivateSound:

I have added this to the query string in the iframe url - in future we can update the Echo360 to follow this option.

{number} startAt:

The handler performs a seek when the video is loaded if this option is present.

Resuming (restarting at the time code that the user left off) works fine in Interactive Video, but not when run in Column.

I'll investigate column mode in more detail today.

Changing the playbackrate

The timing sync of the playback rates is under active development at the moment and this is not specific to h5p.

When using the play button of Interactive Video or the handler's play function directly, ... Audio will only play if the user clicks on the video to play it.

I have addressed this by adding allow="fullscreen, autoplay" to the iframe which grants permissions to play the audio.

@echo360-damyon
Copy link
Contributor Author

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.

Copy link
Contributor

@otacke otacke left a 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.

MHod-101 and others added 8 commits March 7, 2024 13:44
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
@otacke
Copy link
Contributor

otacke commented Mar 25, 2024

@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:

  • Video should use the full player canvas. Additional platform features should be added in an overlay as in YouTube or Vimeo, not next to the video.
  • When videos run standalone, e.g. in Column, then they should receive proper controls (unless deactivated in the options), so “play”, “pause”, “seek”, “mute”, “full screen” + ”current time / duration” (optionally playback rate)
  • When videos run inside Interactive Book (or any other parent content type which requests to deactivate the full screen button), no full screen button should be visible.
  • When videos are run inside Interactive Video, when seeking, the knob jumps back to the original position briefly and then jumps back to the requested position. It feels a little odd (doesn’t happen for YouTube, for instance) and should probably be fixed, but that’s up to the UX team of H5P Group to decide.
  • When resizing, there’s some noticeable flickering going on and should probably be fixed, but that’s up to the UX team of H5P Group to decide.
  • When running the video standalone where one currently needs to click on the video to play/pause it, this click doesn’t always seem to be registered properly. One sometimes needs to click multiple times to see an effect.

@echo360-damyon
Copy link
Contributor Author

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:

"Video should use the full player canvas..."

  • This is not reasonable. Our player has a lot of features you aren't aware of and it's not feasible to re-implement the controls as an overlay.

"When videos run standalone, e.g. in Column, then they should receive proper controls..."

  • They are if the option is set to display controls - this may not have appeared not to work because of the version on our QA environment when you tested.

"When videos run inside Interactive Book ... no full screen button should be visible."

  • It is not visible - this may not have appeared not to work because of the version on our QA environment when you tested.

"When videos are run ...seeking jumps back and forward"

  • This happens in our normal player even outside of H5p and is in the backlog of things which we will address in time.

"When resizing, there’s some noticeable flickering"

There is is minimal flickering while resizing - this can be addressed in future but is not in scope of this H5P change.

"When running the video standalone...this click doesn’t always seem to be registered properly. "

This was addressed and is to do with the iframe permissions.

@otacke
Copy link
Contributor

otacke commented Apr 9, 2024

@echo360-damyon Thanks for getting back to me.

"Video should use the full player canvas..."

  • This is not reasonable. Our player has a lot of features you aren't aware of and it's not feasible to re-implement the controls as an overlay.

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.

"When videos run standalone, e.g. in Column, then they should receive proper controls..."

  • They are if the option is set to display controls - this may not have appeared not to work because of the version on our QA environment when you tested.

Yup, seems to be working nicely now.

  • One thing that H5P Group may not be too happy about is using the title attribute on the buttons. While this is a normal HTML feature, it seems to cause trouble with some screen readers. If this is a custom view for H5P, then it might not cause to much trouble to remove it. But it's your side of the implementation. And again, that's not up for me to decide.

  • When used with the keyboard, the play button works as it should, but all the other buttons don't trigger their respective function, but also trigger play/pause.

"When videos run inside Interactive Book ... no full screen button should be visible."

  • It is not visible - this may not have appeared not to work because of the version on our QA environment when you tested.

Still doesn't seem to work, but this seems in fact to be an issue with H5P.InteractiveBook/H5P.Column/H5P.Video.

"When videos are run ...seeking jumps back and forward"

  • This happens in our normal player even outside of H5p and is in the backlog of things which we will address in time.

Will let H5P Group know.

"When resizing, there’s some noticeable flickering"

There is is minimal flickering while resizing - this can be addressed in future but is not in scope of this H5P change.

Will let H5P Group know. This is up to their UX team.

"When running the video standalone...this click doesn’t always seem to be registered properly. "

This was addressed and is to do with the iframe permissions.

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.

echo360-damyon and others added 22 commits May 2, 2024 12:22
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
@devland
Copy link
Contributor

devland commented May 2, 2024

When used in h5p-course-presentation, the video plays but it doesn't take up all the space the editor allows it.
image

@devland devland merged commit c047a8e into h5p:master May 3, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants