souvenir/src/services/capture.js

98 lines
2.5 KiB
JavaScript
Raw Normal View History

2019-05-21 13:51:22 +00:00
import { task, of as taskOf } from 'folktale/concurrency/task'
import { makeRectangle, crop } from '/services/rectangle.js'
import {
GIF_WIDTH,
GIF_HEIGHT,
GIF_FRAME_RATE
} from '/constants.js'
2019-05-21 13:51:22 +00:00
export function capture({ mediaStream, facingMode }, duration, progressCallback) {
const delayTime = 1000 / GIF_FRAME_RATE
const totalFrames = duration / 1000 * GIF_FRAME_RATE
2019-05-21 13:51:22 +00:00
if (totalFrames < 1) {
return taskOf({
imageWidth: GIF_WIDTH,
imageHeight: GIF_HEIGHT,
imageDataList: [],
delayTime
})
}
2019-05-21 13:51:22 +00:00
return task(resolver => {
const video = document.createElement('video')
video.setAttribute('playsinline', '')
video.setAttribute('webkit-playsinline', '')
video.srcObject = mediaStream
video.play()
2019-05-21 13:51:22 +00:00
video.addEventListener('canplaythrough', afterVideoAvailable, {
once: true
})
2019-05-21 13:51:22 +00:00
resolver.cleanup(() => {
video.removeEventListener('canplaythrough', afterVideoAvailable)
})
2019-03-10 04:37:22 +00:00
2019-05-21 13:51:22 +00:00
function afterVideoAvailable() {
const canvas = document.createElement('canvas')
canvas.width = GIF_WIDTH
canvas.height = GIF_HEIGHT
2019-03-10 04:37:22 +00:00
2019-05-21 13:51:22 +00:00
const canvasContext = canvas.getContext('2d')
2019-03-10 04:37:22 +00:00
2019-05-21 13:51:22 +00:00
if (facingMode === 'user' || facingMode === 'unknow') {
canvasContext.translate(canvas.width, 0)
canvasContext.scale(-1, 1)
}
2019-05-21 13:51:22 +00:00
const imageDataList = []
const destinationRectangle = makeRectangle(0, 0, canvas.width, canvas.height)
const soureRectangle = crop(makeRectangle(0, 0, video.videoWidth, video.videoHeight))
2019-05-21 13:51:22 +00:00
captureFrame()
const intervalId = setInterval(captureFrame, delayTime)
resolver.cleanup(() => {
clearInterval(intervalId)
})
function captureFrame () {
canvasContext.drawImage(
video,
soureRectangle.x,
soureRectangle.y,
soureRectangle.width,
soureRectangle.height,
destinationRectangle.x,
destinationRectangle.y,
destinationRectangle.width,
destinationRectangle.height
)
const imageData = canvasContext.getImageData(
destinationRectangle.x,
destinationRectangle.y,
destinationRectangle.width,
destinationRectangle.height
)
imageDataList.push(imageData)
progressCallback(imageDataList.length / totalFrames)
if (imageDataList.length >= totalFrames) {
resolver.resolve({
imageDataList,
imageWidth: GIF_WIDTH,
imageHeight: GIF_HEIGHT,
delayTime
})
}
}
}
})
2019-05-21 13:51:22 +00:00
}