From 83f5b24a438516c156e1fc6bfa6f4328ae07752e Mon Sep 17 00:00:00 2001 From: Francisco Baio Dias Date: Fri, 8 Feb 2019 14:29:44 +0100 Subject: [PATCH] fix: handle cases when loadeddata is never triggered --- src/get-video-info.js | 68 +++++++++++++++++++++++++++++++++++ src/video-recorder.js | 46 +++--------------------- src/video-recorder.stories.js | 2 +- 3 files changed, 73 insertions(+), 43 deletions(-) create mode 100644 src/get-video-info.js diff --git a/src/get-video-info.js b/src/get-video-info.js new file mode 100644 index 0000000..6b3cae9 --- /dev/null +++ b/src/get-video-info.js @@ -0,0 +1,68 @@ +export const captureThumb = videoTag => + new Promise((resolve, reject) => { + const canvas = document.createElement('canvas') + canvas.width = videoTag.videoWidth + canvas.height = videoTag.videoHeight + canvas.getContext('2d').drawImage( + videoTag, + 0, // top + 0, // left + videoTag.videoWidth, + videoTag.videoHeight + ) + canvas.toBlob(thumbnail => { + resolve(thumbnail) + }) + }) + +const getVideoInfo = videoBlob => + new Promise((resolve, reject) => { + const videoTag = document.createElement('video') + videoTag.preload = 'metadata' + videoTag.muted = true + videoTag.defaultMuted = true + videoTag.playsInline = true + videoTag.autoplay = true + + let resolved = false + + const handleTimeout = () => { + resolved = true + resolve({ + duration: null, + thumbnail: null + }) + videoTag.remoteEventListener('loadeddata', handleLoadedData) + window.URL.revokeObjectURL(videoTag.src) + } + + let timeout = setTimeout(handleTimeout, 1000) + + const handleLoadedData = () => { + const duration = videoTag.duration * 1000 + + captureThumb(videoTag) + .then(thumbnail => { + videoTag.pause() + if (!resolved) { + clearTimeout(timeout) + resolved = true + resolve({ duration, thumbnail }) + } + window.URL.revokeObjectURL(videoTag.src) + }) + .catch(err => { + if (!resolved) { + alert(`thumb error ${err}`) + clearTimeout(timeout) + resolved = true + reject(err) + } + }) + } + + videoTag.addEventListener('loadeddata', handleLoadedData) + videoTag.src = window.URL.createObjectURL(videoBlob) + }) + +export default getVideoInfo diff --git a/src/video-recorder.js b/src/video-recorder.js index b7abe54..5dd2a1c 100644 --- a/src/video-recorder.js +++ b/src/video-recorder.js @@ -6,6 +6,7 @@ import ErrorView from './defaults/error-view' import DisconnectedView from './defaults/disconnected-view' import LoadingView from './defaults/loading-view' import renderActions from './defaults/render-actions' +import getVideoInfo, { captureThumb } from './get-video-info' // data shows up on some browsers // approx every 2 seconds @@ -57,47 +58,6 @@ const Video = styled.video` ${props => props.onClick && 'cursor: pointer;'}; ` -const captureThumb = videoTag => - new Promise((resolve, reject) => { - const canvas = document.createElement('canvas') - canvas.width = videoTag.videoWidth - canvas.height = videoTag.videoHeight - canvas.getContext('2d').drawImage( - videoTag, - 0, // top - 0, // left - videoTag.videoWidth, - videoTag.videoHeight - ) - canvas.toBlob(thumbnail => { - resolve(thumbnail) - }) - }) - -const getVideoInfo = videoBlob => - new Promise((resolve, reject) => { - const videoTag = document.createElement('video') - videoTag.preload = 'metadata' - videoTag.muted = true - videoTag.defaultMuted = true - videoTag.playsInline = true - videoTag.autoplay = true - - videoTag.addEventListener('loadeddata', function () { - const duration = videoTag.duration * 1000 - - captureThumb(videoTag) - .then(thumbnail => { - window.URL.revokeObjectURL(this.src) - videoTag.pause() - resolve({ duration, thumbnail }) - }) - .catch(reject) - }) - - videoTag.src = window.URL.createObjectURL(videoBlob) - }) - export default class VideoRecorder extends Component { constructor (props) { super(props) @@ -423,7 +383,9 @@ export default class VideoRecorder extends Component { extension ) }) - .catch(this.handleError) + .catch(err => { + this.handleError(err) + }) } handleOpenVideoInput () { diff --git a/src/video-recorder.stories.js b/src/video-recorder.stories.js index 07cbedf..d9591c4 100644 --- a/src/video-recorder.stories.js +++ b/src/video-recorder.stories.js @@ -21,7 +21,7 @@ const handleRecordingComplete = ( duration ) => { const urlCreator = window.URL || window.webkitURL - const thumbUrl = urlCreator.createObjectURL(thumbnailBlob) + const thumbUrl = thumbnailBlob && urlCreator.createObjectURL(thumbnailBlob) const videoUrl = urlCreator.createObjectURL(videoBlob) console.log('Video Blob', videoBlob.size, videoBlob, videoUrl) console.log('Thumb Blob', thumbnailBlob, thumbUrl)