From e9d4becea1ce10fc6104520d9703da61773014c4 Mon Sep 17 00:00:00 2001 From: Jack Reed <phillipjreed@gmail.com> Date: Thu, 24 Sep 2020 07:51:07 -0600 Subject: [PATCH] Basic support for subtitles/captions --- src/components/VideoViewer.js | 10 ++++++++-- src/containers/VideoViewer.js | 3 ++- src/lib/MiradorCanvas.js | 9 +++++++++ src/state/selectors/canvases.js | 8 ++++++++ 4 files changed, 27 insertions(+), 3 deletions(-) diff --git a/src/components/VideoViewer.js b/src/components/VideoViewer.js index 3e72dbcc2..2eec0d0ab 100644 --- a/src/components/VideoViewer.js +++ b/src/components/VideoViewer.js @@ -6,8 +6,7 @@ export class VideoViewer extends Component { /* eslint-disable jsx-a11y/media-has-caption */ /** */ render() { - const { classes, videoResources } = this.props; - + const { captions, classes, videoResources } = this.props; return ( <div className={classes.container}> <video controls className={classes.video}> @@ -16,6 +15,11 @@ export class VideoViewer extends Component { <source src={video.id} type={video.getFormat()} /> </Fragment> ))} + {captions.map(caption => ( + <Fragment key={caption.id}> + <track src={caption.id} label={caption.getLabel()} srcLang={caption.getProperty('language')} /> + </Fragment> + ))} </video> </div> ); @@ -24,10 +28,12 @@ export class VideoViewer extends Component { } VideoViewer.propTypes = { + captions: PropTypes.arrayOf(PropTypes.object), classes: PropTypes.objectOf(PropTypes.string).isRequired, videoResources: PropTypes.arrayOf(PropTypes.object), }; VideoViewer.defaultProps = { + captions: [], videoResources: [], }; diff --git a/src/containers/VideoViewer.js b/src/containers/VideoViewer.js index 97f762036..f9480ac9b 100644 --- a/src/containers/VideoViewer.js +++ b/src/containers/VideoViewer.js @@ -4,11 +4,12 @@ import { withTranslation } from 'react-i18next'; import { withStyles } from '@material-ui/core'; import { withPlugins } from '../extend/withPlugins'; import { VideoViewer } from '../components/VideoViewer'; -import { getVisibleCanvasVideoResources } from '../state/selectors'; +import { getVisibleCanvasCaptions, getVisibleCanvasVideoResources } from '../state/selectors'; /** */ const mapStateToProps = (state, { windowId }) => ( { + captions: getVisibleCanvasCaptions(state, { windowId }) || [], videoResources: getVisibleCanvasVideoResources(state, { windowId }) || [], } ); diff --git a/src/lib/MiradorCanvas.js b/src/lib/MiradorCanvas.js index ebd45f2f5..3c490aed0 100644 --- a/src/lib/MiradorCanvas.js +++ b/src/lib/MiradorCanvas.js @@ -99,6 +99,15 @@ export default class MiradorCanvas { return flatten(resources.filter((resource) => resource.getProperty('type') === 'Sound')); } + /** */ + get vttContent() { + const resources = flattenDeep([ + this.canvas.getContent().map(i => i.getBody()), + ]); + + return flatten(resources.filter((resource) => resource.getProperty('format') === 'text/vtt')); + } + /** */ get resourceAnnotations() { return flattenDeep([ diff --git a/src/state/selectors/canvases.js b/src/state/selectors/canvases.js index 71b3e274e..a64088056 100644 --- a/src/state/selectors/canvases.js +++ b/src/state/selectors/canvases.js @@ -192,6 +192,14 @@ export const getVisibleCanvasVideoResources = createSelector( .map(canvas => new MiradorCanvas(canvas).videoResources)), ); +export const getVisibleCanvasCaptions = createSelector( + [ + getVisibleCanvases, + ], + canvases => flatten(canvases + .map(canvas => new MiradorCanvas(canvas).vttContent)), +); + export const getVisibleCanvasAudioResources = createSelector( [ getVisibleCanvases, -- GitLab