视频捕获期间移动 safari 内存不足
Mobile safari out of memory during video capturing
我的 React class 有两个主要元素。 Canvas 和视频。
我获取视频流并以 30fps 将其渲染到 canvas。
class GetImage extends Component {
constructor() {
super();
this.constraints = {
video: {
width: { ideal: 2048 },
height: { ideal: 1080 },
facingMode: {
exact: 'environment'
}
}
}
}
componentDidMount() {
setVideo(this.video, this.constraints, this.readyToPlayVideo)
}
capture = () => {
const { video } = this
let canvas = document.createElement('canvas')
canvas.width = video.videoWidth
canvas.height = video.videoHeight
let context = canvas.getContext('2d')
context.clearRect(0, 0, canvas.width, canvas.height);
context.drawImage(this.video, 0, 0, canvas.width, canvas.height)
this.setState({ capture: canvas.toDataURL('image/jpeg') })
stopVideo()
}
readyToPlayVideo = () => {
const { canvas, video } = this
const { offsetHeight, offsetWidth } = video
const ctx = canvas.getContext('2d')
ctx.canvas.setAttribute('height', offsetHeight)
ctx.canvas.setAttribute('width', offsetWidth)
const timeout = 1000 / 30 // drawing at 30fps
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
let _listener = () => {
(function loop() {
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
ctx.drawImage(video, 0, 0)
setTimeout(loop, timeout)
})()
}
_listener();
}
retake = () =>
this.setState({ capture: null },
() => {
setVideo(this.video, this.constraints, this.readyToPlayVideo, this.handleError)
}
)
render() {
return (
<div>
<video
style={{ visibility: 'hidden'}}
ref={video => (this.video = video)}
playsInline
autoPlay
/>
<canvas ref={canvas => (this.canvas = canvas)}/>
</div>
)
}
}
到目前为止一切顺利。
但是我遇到了移动版 Safari 的问题。看起来它保留了内存中创建的每个 Canvas 对象。
拍了几张照片后,Safari 崩溃 "out of memory"。
我已经在渲染新图像之前执行了 clearRect,但这没有帮助。
不确定这是否能 100% 解决您的问题,但这可能会有所帮助。不要为你的动画使用 setInterval
,而是使用 window.requestAnimationFrame
.
这是一个例子
var requestAnimFrame = (function() {
return window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.msRequestAnimationFrame ||
function( callback ) {
window.setTimeout(callback, 1000 / 30);
};
})();
function loop(){
requestAnimFrame(loop);
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
ctx.drawImage(video, 0, 0);
setTimeout(loop, timeout);
}
loop();
再说一次,我不是 100% 确定这会解决您的问题,但是,它可能会有所帮助。如果您还有其他问题,请告诉我。
希望对您有所帮助!
这里有几个问题需要解决。首先,您的 loop
函数中似乎有一个循环引用;您正在调用函数内的函数。
因此,自动播放视频(渲染时)不会停止..导致 'out of memory' 错误。
此外,我认为最佳做法是创建一个 componentDidUnmount
函数来销毁视频(当不再需要时)。使用.dispose
销毁视频。
希望对您有所帮助
我的 React class 有两个主要元素。 Canvas 和视频。 我获取视频流并以 30fps 将其渲染到 canvas。
class GetImage extends Component {
constructor() {
super();
this.constraints = {
video: {
width: { ideal: 2048 },
height: { ideal: 1080 },
facingMode: {
exact: 'environment'
}
}
}
}
componentDidMount() {
setVideo(this.video, this.constraints, this.readyToPlayVideo)
}
capture = () => {
const { video } = this
let canvas = document.createElement('canvas')
canvas.width = video.videoWidth
canvas.height = video.videoHeight
let context = canvas.getContext('2d')
context.clearRect(0, 0, canvas.width, canvas.height);
context.drawImage(this.video, 0, 0, canvas.width, canvas.height)
this.setState({ capture: canvas.toDataURL('image/jpeg') })
stopVideo()
}
readyToPlayVideo = () => {
const { canvas, video } = this
const { offsetHeight, offsetWidth } = video
const ctx = canvas.getContext('2d')
ctx.canvas.setAttribute('height', offsetHeight)
ctx.canvas.setAttribute('width', offsetWidth)
const timeout = 1000 / 30 // drawing at 30fps
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
let _listener = () => {
(function loop() {
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
ctx.drawImage(video, 0, 0)
setTimeout(loop, timeout)
})()
}
_listener();
}
retake = () =>
this.setState({ capture: null },
() => {
setVideo(this.video, this.constraints, this.readyToPlayVideo, this.handleError)
}
)
render() {
return (
<div>
<video
style={{ visibility: 'hidden'}}
ref={video => (this.video = video)}
playsInline
autoPlay
/>
<canvas ref={canvas => (this.canvas = canvas)}/>
</div>
)
}
}
到目前为止一切顺利。 但是我遇到了移动版 Safari 的问题。看起来它保留了内存中创建的每个 Canvas 对象。
拍了几张照片后,Safari 崩溃 "out of memory"。 我已经在渲染新图像之前执行了 clearRect,但这没有帮助。
不确定这是否能 100% 解决您的问题,但这可能会有所帮助。不要为你的动画使用 setInterval
,而是使用 window.requestAnimationFrame
.
这是一个例子
var requestAnimFrame = (function() {
return window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.msRequestAnimationFrame ||
function( callback ) {
window.setTimeout(callback, 1000 / 30);
};
})();
function loop(){
requestAnimFrame(loop);
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
ctx.drawImage(video, 0, 0);
setTimeout(loop, timeout);
}
loop();
再说一次,我不是 100% 确定这会解决您的问题,但是,它可能会有所帮助。如果您还有其他问题,请告诉我。
希望对您有所帮助!
这里有几个问题需要解决。首先,您的 loop
函数中似乎有一个循环引用;您正在调用函数内的函数。
因此,自动播放视频(渲染时)不会停止..导致 'out of memory' 错误。
此外,我认为最佳做法是创建一个 componentDidUnmount
函数来销毁视频(当不再需要时)。使用.dispose
销毁视频。
希望对您有所帮助