Skip to content

Commit

Permalink
Merge pull request #5351 from avalonmediasystem/videojs-embed
Browse files Browse the repository at this point in the history
Move the embedded player from MEjs to Videojs
  • Loading branch information
masaball authored Sep 8, 2023
2 parents 4fa129c + 3c957cf commit 590fa57
Show file tree
Hide file tree
Showing 7 changed files with 234 additions and 68 deletions.
12 changes: 8 additions & 4 deletions app/assets/javascripts/application.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
/*
/*
* Copyright 2011-2023, The Trustees of Indiana University and Northwestern
* University. Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
*
*
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software distributed
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
Expand Down Expand Up @@ -59,4 +59,8 @@
//= stub media_player_wrapper/mejs4_link_back
//= stub media_player_wrapper/mejs4_plugin_playlist_items

// Require VideoJS and VideoJS quality selector for embedded player
//= require video.js/dist/video.min.js
//= require @silvermine/videojs-quality-selector/dist/js/silvermine-videojs-quality-selector.min.js

//= require_tree .
11 changes: 7 additions & 4 deletions app/assets/stylesheets/application.scss
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
/*
/*
* Copyright 2011-2023, The Trustees of Indiana University and Northwestern
* University. Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
*
*
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software distributed
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
Expand Down Expand Up @@ -60,3 +60,6 @@
@import 'avalon';

@import "datatables";

@import "video.js/dist/video-js.css";
@import "@silvermine/videojs-quality-selector/dist/css/quality-selector.css";
114 changes: 94 additions & 20 deletions app/assets/stylesheets/embed.scss
Original file line number Diff line number Diff line change
@@ -1,42 +1,116 @@
/*
/*
* Copyright 2011-2023, The Trustees of Indiana University and Northwestern
* University. Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
*
*
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software distributed
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
* --- END LICENSE_HEADER BLOCK ---
*/

body {
background-color: #000000;
width: 100%;
height: 100%;
margin: 0;
overflow: hidden;
.video-container {
position: absolute;
}

.container-fluid {
padding: 0;
.video-js {
position: relative;
z-index: 0;
}

.mejs-layers {
pointer-events: none !important;
.video-title {
position: absolute;
z-index: 1;
top: 5px;
left: 8px;
}

#content, #content > div {
height: 100%;
max-width: none;
.video-title .video-link {
color: white;
font-size:150%;
}

.mejs__audio {
position: absolute;
bottom: 0;
.video-js.vjs-playing + .video-title {
display: none;
}

// @silvermine/videojs-quality-selector
.vjs-menu {
li {
font-size: 1em;
}
}

.video-js .vjs-control-bar {
/* Audio: Make the controlbar visible by default */
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
/* Increase the control-bar icons/text size */
font-size: 120%;
}

/* Make player height minimum to the controls height so when we hide
video/poster area the controls are displayed correctly. */
.video-js.vjs-audio {
min-height: 3.7em;
}

.video-js .vjs-progress-control:hover .vjs-play-progress:after {
display: none;
}

/* Show poster image when playback ends */
.video-js.vjs-ended .vjs-poster {
display: block;
}

.video-js .vjs-current-time {
display: block;
}

/* Put playhead on top of markers */
.video-js .vjs-play-progress:before {
z-index: 101;
}

/* time-control elements */
.video-js .vjs-time-control {
min-width: 0.5rem;
padding: 0 0.25rem;
}

.vjs-time-divider {
display: block;
}

.vjs-duration {
display: block !important;
}

/* big-play button */
.video-js .vjs-big-play-button {
margin-left: auto;
margin-right: auto;
height: 2.5rem;
width: 2.5rem;
line-height: 2.5rem;
border-radius: 50%;
scale: 2;
border: 0.1rem solid #fff;
}

/* captions button selection */
.captions-on {
border-bottom: 0.45rem ridge;
}

.vjs-custom-external-link .vjs-icon-placeholder {
font-size: 120%;
}
33 changes: 0 additions & 33 deletions app/views/master_files/_mejs4_player_js.html.erb

This file was deleted.

8 changes: 3 additions & 5 deletions app/views/master_files/_player.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,10 @@ Unless required by applicable law or agreed to in writing, software distributed
--- END LICENSE_HEADER BLOCK ---
%>
<%= render partial: 'modules/player/section', locals: {section: @master_file, section_info: @stream_info, f_start: @f_start, f_end: @f_end} %>
<%= render partial: 'modules/player/section', locals: {section: @master_file, section_info: @stream_info, f_start: @f_start, f_end: @f_end} %>
<% content_for :page_scripts do %>

<%= render partial: "mejs4_player_js", locals: {section: @master_file, section_info: @stream_info} %>

<script>
<%# Add an offscreen button to allow for proper keyboard navigation through player controls %>
$('#content').append('<button id="after-player" style="position:absolute;top:-1000px"></button>')
Expand All @@ -36,7 +34,7 @@ Unless required by applicable law or agreed to in writing, software distributed
</script>

<style>
a { text-decoration: none; }
a:hover { text-decoration: underline }
a { text-decoration: none; }
a:hover { text-decoration: underline }
</style>
<% end %>
5 changes: 3 additions & 2 deletions app/views/modules/player/_section.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,9 @@ Unless required by applicable law or agreed to in writing, software distributed
--- END LICENSE_HEADER BLOCK ---
%>
<section id="content" style="width: 100%;" tabIndex="-1">
<% if section.present? and section.derivatives.present? %>
<% if section.present? && section.derivatives.present? && @master_file.present? %>
<%= render partial: 'modules/player/video_js_element', locals: {section: section, section_info: section_info, f_start: @f_start, f_end: @f_end} %>
<% elsif section.present? && section.derivatives.present? && @playlist.present? %>
<% if section_info[:is_video] %>
<%= render partial: 'modules/player/video_element', locals: {section: section, section_info: section_info, f_start: @f_start, f_end: @f_end} %>
<% else %>
Expand Down
119 changes: 119 additions & 0 deletions app/views/modules/player/_video_js_element.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
<%#
Copyright 2011-2023, The Trustees of Indiana University and Northwestern
University. Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed
under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied. See the License for the
specific language governing permissions and limitations under the License.
--- END LICENSE_HEADER BLOCK ---
%>
<%= master_file_meta_properties(section) do %>
<% control_bar_options = if section_info[:is_video]
{
"children": [
'playToggle',
'volumePanel',
'progressControl',
'currentTimeDisplay',
'timeDivider',
'durationDisplay',
'subsCapsButton',
'qualitySelector'
],
fullscreenToggle: section_info[:is_video] ? true : false
}
else
{
"children": [
'playToggle',
'volumePanel',
'progressControl',
'currentTimeDisplay',
'timeDivider',
'durationDisplay'
]
}
end %>
<% @videojs_options = {"aspectRatio": section_info[:is_video] ? '16:9' : '1:0',
"autoplay": false,
"width": @player_width || 480,
"height": @player_height || 270,
"bigPlayButton": section_info[:is_video] ? true : false,
"poster": section_info[:is_video] ? section_info[:poster_image] : false,
"fluid": true,
"responsive": true,
"preload": "auto",
"controlBar": control_bar_options,
"userActions": {
hotkeys: true
}
}.compact.to_json %>

<div class='video-container' style="width:100%; height:100%;">
<video-js id="video-js-embed-<%= @master_file.id %>"
class="vjs-big-play-centered"
controls
style="width:100%; height:100%;"
data-setup='<%= @videojs_options %>'>
<% section_info[:stream_hls].each do |hls| %>
<source src="<%= hls[:url] %>" type="application/x-mpegURL" data-quality="<%= hls[:quality] %>" label="<%= hls[:quality] %>"/>
<% end %>
<% if section_info[:caption_paths].present? %>
<% section_info[:caption_paths].each do |c| %>
<track <% if c[:label] %>label="<%= c[:label] %>" <% end %> srclang="<%= c[:language] %>" kind="subtitles" type="<%= c[:mime_type] %>" src="<%= c[:path] %>"></track>
<% end %>
<% end %>
</video-js>
<% if section_info[:is_video] %>
<label class='video-title' id='video-title-<%= @master_file.id %>'>
<a class='video-link' id='video-link-<%= @master_file.id %>' href="<%= master_file_url(@master_file.id) %>" target="_blank" rel="noreferrer noopener"><%= @master_file.title || @master_file.media_object.title %></a>
</label>
<% end %>
</div>
<% end %>
<% content_for :page_scripts do %>
<script>
var player = videojs(document.querySelector('#video-js-embed-<%= @master_file.id %>'));
var ButtonComponent = videojs.getComponent('Button');
var viewInRepoButton = new ButtonComponent(player, {
clickHandler: function(event) {
window.open('<%= master_file_url(@master_file.id) %>', '_blank').focus();
}
});

viewInRepoButton.addClass('vjs-custom-external-link');
let newButton = player.controlBar.addChild(viewInRepoButton, {}, <%= section_info[:is_video] ? 8 : 6 %>);
newButton.controlText('View in Repository');

document.querySelector('.vjs-custom-external-link .vjs-icon-placeholder').innerHTML = '<svg xmlns="http://www.w3.org/2000/svg" height="1em" viewBox="0 0 512 512"><!--! Font Awesome Free 6.4.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. --><style>svg{fill:#ffffff}</style><path d="M320 0c-17.7 0-32 14.3-32 32s14.3 32 32 32h82.7L201.4 265.4c-12.5 12.5-12.5 32.8 0 45.3s32.8 12.5 45.3 0L448 109.3V192c0 17.7 14.3 32 32 32s32-14.3 32-32V32c0-17.7-14.3-32-32-32H320zM80 32C35.8 32 0 67.8 0 112V432c0 44.2 35.8 80 80 80H400c44.2 0 80-35.8 80-80V320c0-17.7-14.3-32-32-32s-32 14.3-32 32V432c0 8.8-7.2 16-16 16H80c-8.8 0-16-7.2-16-16V112c0-8.8 7.2-16 16-16H192c17.7 0 32-14.3 32-32s-14.3-32-32-32H80z"/></svg>'

player.currentTime(<%= @stream_info['t'][0] %>);

function handleTimeUpdate(curTime) {
var start = <%= @stream_info['t'] ? @stream_info['t'][0] : 0 %>;
var end = <%= @stream_info['t'][1] || @stream_info[:duration] %>;

if (curTime < start) {
player.currentTime(start);
}
if (curTime >= end) {
player.trigger('ended');
player.pause();
player.currentTime(start);
}
};

player.on('timeupdate', () => {
handleTimeUpdate(player.currentTime());
});
</script>
<% end %>

0 comments on commit 590fa57

Please sign in to comment.