mirror of
https://github.com/GuerillaStudio/souvenir.git
synced 2025-01-20 18:30:20 +00:00
refactor(capture): fix delay before completion
This commit is contained in:
parent
b403a78437
commit
b741779265
1 changed files with 58 additions and 56 deletions
|
@ -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))
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue