PHP - 在视频上传期间提取帧

PHP - Extract frame during Video upload

本文关键字:提取 视频 PHP      更新时间:2023-09-26

我在寻找这是否可能时遇到了问题(在任何地方都找不到信息)。是否可以在视频上传过程中提取帧(缩略图)?如果可以提取用户端,使用 jscript 进行提取也是一种选择。

感谢您的帮助!

自这个问题发布以来快进近五年,现在的答案是肯定的!

现场演示

如何使用JavaScript在视频上传期间提取帧

在显示代码之前,我们将执行以下操作:

  1. 在输入元素上设置事件处理程序,该元素将上传视频
  2. 从文件系统中选择文件后,使用 URL 对象创建指向本地视频文件的 URL。
  3. 将该 URL 加载到 video 元素中。
  4. 将视频加载到内存中后,在canvas对象上绘制帧。
  5. 现在,将画布上呈现的框架导出到image元素中(或者可以选择将该图像作为数据 url 发送到服务器)。
<小时 />
<input type="file" id="upload"/>
<img id="thumbnail"/>
<script>
var input = document.getElementById('upload');
var img = document.getElementById('thumbnail');
input.addEventListener('change', function(event){
    var file = this.files[0];
    var url = URL.createObjectURL(file);
    var video = document.createElement('video');
    video.src = url;
    var snapshot = function(){
        var canvas = document.createElement('canvas');
        var ctx = canvas.getContext('2d');
        ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
        img.src = canvas.toDataURL('image/png');
        video.removeEventListener('canplay', snapshot);
    };
    video.addEventListener('canplay', snapshot);
});
</script>
我认为在

php 中没有很好的方法可以做到这一点。(https://stackoverflow.com/a/1309425/1488032)

如果它不仅仅是您租用的一些网络空间,而是有权在服务器上安装和运行其他软件,我建议使用 ffmpeg 之类的东西,并使用 system()、passthru() 或 exec() 从 php 中调用它来提取您想要的内容并再次在 php 中进行其余处理。

我正在运行一个依赖于嵌入在 xhtml 中的 svg 图像的浏览器游戏,但某些浏览器(尤其是移动浏览器)不支持完整的 svg 语法。在这种情况下,我使用这样的system()调用来使用imagemagick的转换二进制文件进行svg到png的转换,并将结果显示在我的页面上。

system("echo '$svgString' | convert svg:- png:- | base64");

我想你必须回到类似的东西。

以下是有关使用 ffmpeg 提取帧的一些信息:http://ubuntuforums.org/showthread.php?t=1141293

Javascript: no.

上传期间:否。

上传后,是的。

"Dev"在评论中提供了正确的链接,但您应该做的是将视频保存到您的服务器,然后运行 ffMpeg 来抓取图像。你可以在这里下载ffMPEG:http://ffmpeg.org/download.html(如果你对自己构建没有信心,请获取你需要的构建 - 有Linux和Windows构建)。

文档在这里: http://ffmpeg.org/ffmpeg.html 但是在 http://linuxers.org/tutorial/how-extract-images-video-using-ffmpeg 有一个稍微容易阅读的教程,用于抓取图像。

注意:有一个PHP扩展包着"phpFFMPEG",但我建议你不要使用它。只需通过 PHP 中的"exec()"运行所需的命令。检查错误返回值,因为每个 CPU 内核只能运行一次 ffMPEG,因此如果您同时尝试两次,它可能会失败 - 要么排队操作,要么在失败时重试。

首先,您需要选择一个程序来提取帧。 FFMPEG通常用于此目的。无论您选择什么,它都需要能够处理部分文件内容。

PHP 脚本直到整个文件上传

完成后才会开始执行,但 PHP 最近有一个功能,可以在文件上传期间执行不同的 PHP 脚本,并且能够获取上传脚本数据(文件名是你感兴趣的东西)。http://php.net/manual/en/session.upload-progress.php

然后,基本上调用外部程序从监视脚本中提取帧,使用上传处理脚本中上传的临时文件名。

总结一下:将文件上传到 upload.php . monitor.php 将获取正在上传的临时文件名 upload.php ,并提取帧。

基本上,我采用了此线程中提供的罗德里戈-西尔维拉答案并对其进行了修改以供我使用,现在解决方案就像一个魅力。甚至我试图上传用户希望上传的视频的视频缩略图/海报,并将视频和缩略图保存在文件夹中。另外,我不想使用ffmpeg。

这是我所做的:在名为"upload.php"的上传文件中,我有以下代码,对上面的rodrigo-silveira解决方案进行了轻微修改:

上传.php:

<input type="file" id="upload"/>
<img id="thumbnail"/>
<form action="action_page.php" method="post" target="_blank">
<input type="hidden" id="mytext" name="mytext" >
<input type="submit" value="Submit">
</form>

<script>
var input = document.getElementById('upload');
var img = document.getElementById('thumbnail');
input.addEventListener('change', function(event){
    var file = this.files[0];
    var url = URL.createObjectURL(file);
    var video = document.createElement('video');
    video.src = url;
    var snapshot = function(){
        var canvas = document.createElement('canvas');
        var ctx = canvas.getContext('2d');
		canvas.width = 350;
		canvas.height = 250;
        ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
        img.src = canvas.toDataURL('image/png');
		document.getElementById("mytext").value = img.src;
        video.removeEventListener('canplay', snapshot);
    };
	
    video.addEventListener('canplay', snapshot);
});
</script>

上面的 HTML 部分和 JavaScript 都在 upload.php 的 body 标签中。

现在转到action_page.php文件:

<?php
$data = $_POST['mytext'];
$file = "photos/file".time().".png";
$uri = substr($data,strpos($data, ",") + 1);
file_put_contents($file, base64_decode($uri));
?>

将两个PHP文件保存在同一个文件夹中,并在该文件夹中创建另一个名为"photos"的文件夹。您在上传.php页面中选择的视频中的视频缩略图/海报图像将作为png文件保存在"照片"文件夹中。(注意:此解决方案不上传视频,仅上传视频缩略图。但从这里开始,这是直截了当的。