labo-components
Version:
150 lines (130 loc) • 4.99 kB
JSX
import React from 'react';
import PropTypes from 'prop-types';
import TranscriptUtil from '../../../util/TranscriptUtil';
import FlexPlayerUtil from '../../../util/FlexPlayerUtil';
import TimeUtil from "../../../util/TimeUtil";
import { VIEW_LIST, VIEW_WORDCLOUD } from '../ContentAnnotationsColumn';
import TimedList from './TimedList';
import WordCloud from './WordCloud';
import { sanitize } from '../../shared/WordCloudHelpers';
import MediaEvents from '../_MediaEvents';
/*
This component shows ASR transcriptions in a TimedList or WordCloud
*/
export default class ASR extends React.PureComponent {
constructor(props) {
super(props);
}
/* ----------------------- RENDER LIST -------------------*/
//TODO update this to map from an array of TranscriptLines
renderList = (mediaObject, transcript, searchTerm, mediaEvents) => {
// convert transcript to item list for TimedList
const items = transcript.lines.map((item, index) => ({
//TODO the ASR timings need to be fixed for DAAN/IMMIX, then this works properly and the old stuff can go
id: 'ca_' + item.type + '_' + index,
start : item.start,
startLabel : TimeUtil.formatMillisToTime(item.start, mediaObject),
data: item.text
}));
return (
<TimedList
items={items}
mediaEvents={mediaEvents}
searchTerm={searchTerm}
/>
);
};
/* ----------------------- RENDER WORDCLOUD -------------------*/
renderWordCloud(transcript, searchTerm, mediaEvents, mediaObject) {
// get raw word list from transcript
const words = transcript.lines.reduce(
(w, item) => w.concat(item.text.split(' ')),
[]
);
// When click on a word, onSeek the player to the next occurence of the given word
// Start on the start of the ASR item for context
const onWordClick = word => {
// get current player position
const pos = mediaEvents.getData(MediaEvents.PLAYER_POS);
// get next occurence
let hit = null;
transcript.lines.some(item => {
const itemStart = FlexPlayerUtil.timeRelativeToOnAir(
item.start / 1000,
mediaObject
);
// if item in the future, or no first hit
if (itemStart > pos || hit == null) {
// sanitize the words
const words = sanitize(item.text);
word = word.replace('_', ' ');
// if word exists
if (words.indexOf(word) !== -1) {
// store first hit
if (!hit) {
hit = item;
}
// if future hit, store and return
if (itemStart > pos) {
hit = item;
return true;
}
}
}
return false;
});
// check if an item was hit
if (hit != null && mediaObject) {
// Update player by triggering SET_PLAYER_POS event
this.props.mediaEvents.trigger(
MediaEvents.SET_PLAYER_POS,
FlexPlayerUtil.timeRelativeToOnAir(
hit.start / 1000,
mediaObject
)
);
}
};
return (
<WordCloud
words={words}
mediaEvents={mediaEvents}
size={100}
searchTerm={searchTerm}
onClick={onWordClick}
/>
);
}
/* ----------------------- RENDER -------------------*/
render = () => {
if (!this.props.activeMediaObject || !this.props.transcript) {
return null;
}
switch (this.props.view) {
case VIEW_LIST:
return this.renderList(
this.props.activeMediaObject,
this.props.transcript,
this.props.searchTerm,
this.props.mediaEvents
);
case VIEW_WORDCLOUD:
return this.renderWordCloud(
this.props.transcript,
this.props.searchTerm,
this.props.mediaEvents,
this.props.activeMediaObject
);
default:
return null;
}
};
}
ASR.propTypes = {
searchTerm: PropTypes.string.isRequired,
view: PropTypes.string.isRequired,
resource: PropTypes.object.isRequired,
activeMediaObject: PropTypes.object.isRequired,
mediaEvents: PropTypes.object.isRequired,
transcript: PropTypes.object
};