Skip to content

Commit

Permalink
[F] Support webVTT captions on video resources
Browse files Browse the repository at this point in the history
  • Loading branch information
1aurend committed Dec 19, 2024
1 parent 44e1750 commit df0cb72
Show file tree
Hide file tree
Showing 8 changed files with 96 additions and 14 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import styled from "@emotion/styled";

export const Group = styled.div`
display: flex;
flex-wrap: wrap;
gap: 40px;
> * {
inline-size: max(200px, min(calc(50% - 20px), 400px));
display: flex;
flex-direction: column;
> div {
flex-grow: 1;
}
> label {
block-size: 15px;
}
}
`;
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React, { PureComponent } from "react";
import PropTypes from "prop-types";
import Form from "global/components/form";
import { withTranslation } from "react-i18next";
import * as Styled from "./Video.styles";

class ResourceFormKindVideo extends PureComponent {
static displayName = "Resource.Form.Kind.Video";
Expand Down Expand Up @@ -42,15 +43,26 @@ class ResourceFormKindVideo extends PureComponent {

renderVideoAttachmentForm() {
return (
<Form.Upload
layout="square"
label={this.props.t("resources.new.video_file")}
accepts="video"
readFrom="attributes[attachmentFileName]"
name="attributes[attachment]"
remove="attributes[removeAttachment]"
{...this.props}
/>
<Styled.Group>
<Form.Upload
layout="square"
label={this.props.t("resources.new.video_file")}
accepts="video"
readFrom="attributes[attachmentFileName]"
name="attributes[attachment]"
remove="attributes[removeAttachment]"
{...this.props}
/>
<Form.Upload
layout="landscape"
label={this.props.t("resources.new.captions")}
accepts="vtt"
readFrom="attributes[captionsTrackFileName]"
name="attributes[captionsTrack]"
remove="attributes[removeCaptionsTrack]"
{...this.props}
/>
</Styled.Group>
);
}

Expand Down
2 changes: 1 addition & 1 deletion client/src/backend/containers/resource/breadcrumbs.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export const getBreadcrumbs = (resource, project, belongsToJournalIssue, t) => {
}
];

return belongsToJournalIssue
return belongsToJournalIssue && project.relationships.journal
? [
{
to: lh.link("backendJournals"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,8 @@
"presentation": "Presentation",
"interactive": "Interactive",
"resource_kind": "Resource Kind",
"kind": "Kind"
"kind": "Kind",
"captions": "Captions"
},
"properties": {
"title_instructions": "This field accepts Markdown.",
Expand Down
30 changes: 28 additions & 2 deletions client/src/frontend/components/resource-player/Video/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -104,23 +104,49 @@ class ResourcePlayerVideo extends Component {
this.props.dispatch(notificationActions.addNotification(notification));
};

trackRef = el => {
if (!el) return;

el.addEventListener("load", () => {
if (!el.track?.cues) return;
Array.from(el.track.cues).forEach(c => {
// eslint-disable-next-line no-param-reassign
c.line = -3;
});
});
};

renderFileVideo() {
if (!this.state.inBrowser) return null;

const {
variantPosterStyles,
attachmentStyles
attachmentStyles,
captionsTrackUrl
} = this.props.resource.attributes;

// Use the proxy if running over ports in dev to avoid CORS error
const captionsSrc =
process.env.NODE_ENV === "development"
? captionsTrackUrl.replace("3020", "3010")
: captionsTrackUrl;

return (
<Styled.VideoWrapper>
<Video
ref={this.playerRef}
controls={["PlayPause", "Seek", "Time", "Volume", "Fullscreen"]}
poster={variantPosterStyles.mediumLandscape}
onError={this.handleError}
>
<source src={attachmentStyles.original} type="video/mp4" />
{!!captionsTrackUrl && (
<track
kind="captions"
src={captionsSrc}
srcLang="en"
ref={this.trackRef}
/>
)}
</Video>
</Styled.VideoWrapper>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,13 @@ export const VideoWrapper = styled.div`
left: 0;
width: 100%;
height: 100%;
video::cue {
font-size: 16px;
background: rgba(0, 0, 0, 0.75);
color: var(--color-base-neutral-white);
font-family: var(--font-family-heading);
}
`;

export const Video = styled.iframe`
Expand Down
4 changes: 4 additions & 0 deletions client/src/global/components/form/Upload/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,10 @@ export class FormUpload extends Component {
accepts: "application/json",
extensions: "json"
},
vtt: {
accepts: "text/vtt",
extensions: "vtt"
},
any: {
accepts: null,
extensions: null
Expand Down
13 changes: 12 additions & 1 deletion client/src/theme/styles/vendor/react-html5video.js
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,16 @@ export default `
.rh5v-Captions_component {
position: relative;
&:has(.rh5v-Captions_activeTrackItem) {
svg {
fill: var(--hover-color);
&:hover {
fill: var(--color-interaction-dark);
}
}
}
}
.rh5v-Captions_component:hover {
Expand All @@ -178,7 +188,8 @@ export default `
}
.rh5v-Captions_icon {
padding: 5px;
padding: 1px;
margin-block-start: 4px;
}
.rh5v-Captions_trackList {
Expand Down

0 comments on commit df0cb72

Please sign in to comment.