refactor(capture): fix delay before completion

This commit is contained in:
wryk 2019-03-15 20:02:20 +01:00
parent b403a78437
commit b741779265

View file

@ -1,9 +1,6 @@
import EventEmitter from 'eventemitter3' import EventEmitter from 'eventemitter3'
import pEvent from 'p-event'
import { import { makeRectangle, crop } from '/services/rectangle.js'
makeRectangle,
crop
} from '/services/rectangle.js'
import { import {
GIF_WIDTH, GIF_WIDTH,
@ -11,75 +8,80 @@ import {
GIF_FRAME_RATE GIF_FRAME_RATE
} from '/constants.js' } from '/constants.js'
export function capture (mediaStream, duration) { export function capture (mediaStream, duration) {
const emitter = new EventEmitter() const emitter = new EventEmitter()
Promise.resolve().then(() => { Promise.resolve().then(async () => {
const video = document.createElement('video') const delayTime = 1000 / GIF_FRAME_RATE
video.autoplay = true const totalFrames = duration / 1000 * GIF_FRAME_RATE
video.setAttribute('playsinline', '')
video.setAttribute('webkit-playsinline', '') // Well, this is a very low frame rate or very short duration clip
if (totalFrames < 1) {
emitter.emit('done', {
imageWidth: GIF_WIDTH,
imageHeight: GIF_HEIGHT,
imageDataList: [],
delayTime
})
return
}
const imageDataList = []
const canvas = document.createElement('canvas') const canvas = document.createElement('canvas')
canvas.width = GIF_WIDTH canvas.width = GIF_WIDTH
canvas.height = GIF_HEIGHT canvas.height = GIF_HEIGHT
const canvasContext = canvas.getContext('2d') const canvasContext = canvas.getContext('2d')
const destinationRectangle = makeRectangle(0, 0, canvas.width, canvas.height)
const totalFrames = duration / 1000 * GIF_FRAME_RATE const video = document.createElement('video')
video.setAttribute('playsinline', '')
if (totalFrames < 1) { video.setAttribute('webkit-playsinline', '')
resolve([])
}
const delayTime = 1000 / GIF_FRAME_RATE
video.srcObject = mediaStream video.srcObject = mediaStream
video.play()
video.addEventListener('canplay', () => { await pEvent(video, 'canplaythrough')
const soureRectangle = crop(makeRectangle(0, 0, video.videoWidth, video.videoHeight)) const soureRectangle = crop(makeRectangle(0, 0, video.videoWidth, video.videoHeight))
const destinationRectangle = makeRectangle(0, 0, canvas.width, canvas.height)
const imageDataList = [] step()
const intervalId = setInterval(() => { function step() {
if (imageDataList.length < totalFrames) { canvasContext.drawImage(
canvasContext.drawImage( video,
video, soureRectangle.x,
soureRectangle.x, soureRectangle.y,
soureRectangle.y, soureRectangle.width,
soureRectangle.width, soureRectangle.height,
soureRectangle.height, destinationRectangle.x,
destinationRectangle.x, destinationRectangle.y,
destinationRectangle.y, destinationRectangle.width,
destinationRectangle.width, destinationRectangle.height
destinationRectangle.height )
)
const imageData = canvasContext.getImageData( const imageData = canvasContext.getImageData(
destinationRectangle.x, destinationRectangle.x,
destinationRectangle.y, destinationRectangle.y,
destinationRectangle.width, destinationRectangle.width,
destinationRectangle.height destinationRectangle.height
) )
imageDataList.push(imageData) imageDataList.push(imageData)
emitter.emit('progress', imageDataList.length / totalFrames) emitter.emit('progress', imageDataList.length / totalFrames)
} else {
clearInterval(intervalId)
emitter.emit('done', { if (imageDataList.length < totalFrames) {
imageDataList, setTimeout(step, delayTime)
imageWidth: GIF_WIDTH, } else {
imageHeight: GIF_HEIGHT, emitter.emit('done', {
delayTime imageDataList,
}) imageWidth: GIF_WIDTH,
} imageHeight: GIF_HEIGHT,
}, delayTime) delayTime
}) })
}
}
}) })
.catch(error => emitter.emit('error', error)) .catch(error => emitter.emit('error', error))