使用 ffmpeg 从视频生成缩略图并添加到 mysql 数据库

Generate thumbnail from video using ffmpeg and add to mysql database

我是 php 的菜鸟,但我仍在尝试 :) 我正在向数据库制作批量视频 uploader/importer。寻找如何从上传的视频中提取缩略图并将这些缩略图添加到每个视频的 mysql 数据库的想法...:/我正在尝试使用 ffmpeg,但我没有找到如何将其实现到我的代码中的方法...

<?php 
    // Database
    include 'config/database.php'; 

    if(isset($_POST['submit'])){
        
        $url = "localhost/";
        $uploadsDir = "uploads/";
        $allowedExts = array("jpg", "jpeg", "gif", "png", "mp3", "mp4", "wma");
        
        // Velidate if files exist
        if (!empty(array_filter($_FILES['fileUpload']['name']))) {
            
            // Loop through file items
            foreach($_FILES['fileUpload']['name'] as $title=>$val){
                // Get files upload path
                $fileName        = $_FILES['fileUpload']['name'][$title];
                $tempLocation    = $_FILES['fileUpload']['tmp_name'][$title];
                $targetFilePath  = $uploadsDir . $fileName;
                $fileType        = strtolower(pathinfo($targetFilePath, PATHINFO_EXTENSION));
                $withOutExtension = pathinfo($fileName, PATHINFO_FILENAME);
                $uploadDate      = date('Y-m-d H:i:s');
                $uploadOk = 1;


                if(in_array($fileType, $allowedExts)){
                        if(move_uploaded_file($tempLocation, $targetFilePath)){
                            $sqlVal = $withOutExtension;
                            $sqlVal2 = $url . $uploadsDir . $fileName;
                            $sqlVal3 = null;
                            $randomID = rand(1000, 999999);
                            $sqlVal4 = ('<p><video controls="" src="/' . $sqlVal2 . '" width="640" height="360" class="note-video-clip"></video><br></p>');
                            $slug = str_replace(' ', '-', $withOutExtension);;
                            $file = $uploadsDir . $fileName;
                            $filesize = filesize($file); // bytes
                            $filesize = round($filesize / 1024 / 1024, 1);
                            

                        } else {
                            $response = array(
                                "status" => "alert-danger",
                                "message" => "File coud not be uploaded."
                            );
                        }
                    
                } else {
                    $response = array(
                        "status" => "alert-danger",
                        "message" => "I want mp4 file."
                    );
                }
                // Add into MySQL database
                if(!empty($sqlVal)) {
                    $insert = $conn->query("INSERT INTO applications (id, title, description, custom_description, details, image, slug, file_size, license, developer, url, buy_url, type, votes, screenshots, total_votes, counter, hits, category, platform, must_have, featured, pinned, editors_choice, created_at, updated_at) VALUES ('$randomID', '$sqlVal', 'Video .mp4 Live Wallpaper. Animated wallpaper is a cross between a screensaver and desktop wallpaper. Like a normal wallpaper, an animated wallpaper serves as the background on your desktop, which is visible to you only when your workspace is empty, i.e. no program windows block it from view.', '$sqlVal3', '$sqlVal4', '99999.jpg', '$slug', '$filesize MB', 'free', 'n/a', '$sqlVal2', '$sqlVal3', '1', '0.00', '', '0', '0', '1', '22', '6', '1', '1', '0', '1', '2021-11-11 16:55:36', '2021-11-11 16:55:36')");
                    if($insert) {
                        $response = array(
                            "status" => "alert-success",
                            "message" => "Files successfully uploaded."
                        );
                    } else {
                        $response = array(
                            "status" => "alert-danger",
                            "message" => "Files coudn't be uploaded due to database error."
                        );
                    }
                }
            }

        } else {
            // Error
            $response = array(
                "status" => "alert-danger",
                "message" => "Please select a file to upload."
            );
        }
    } 
    
    
    


?>

关于 FFMpeg 部分,我认为开始的一个好方法是实际使用文档中的 PHP-FFMpeg library. The Basic Usage section 包含一个关于如何为给定视频生成帧的示例:

require 'vendor/autoload.php';

$ffmpeg = FFMpeg\FFMpeg::create();
$video = $ffmpeg->open('video.mpg');

$video->frame(FFMpeg\Coordinate\TimeCode::fromSeconds(10))
      ->save('frame.jpg');

一个简化的过程如下:

  1. 用户上传了一个视频,之后视频被转移到另一个 目录。
  2. 现在您可以使用上面的代码段和 frame 方法来获取视频的缩略图。
  3. 图像保存完成后,您只需将其添加到您的数据库中即可。
    • 如果缩略图引用了 table 中的 image 列,您只需插入文件名 frame.jpg(甚至是完整的文件路径 /public/path/to/frame.jpg).
    • 如果缩略图引用了您 table 中的 screenshots 列,并且您希望视频有多个缩略图,那么您应该考虑创建一个新的 table one-to-many 关系(从您的 video/application 到新的 table,例如 thumbnails
  4. 然后当用户到达应该显示图像的页面时,只需从 table select 并使用 <img> 标签显示它(使用 public 文件路径).

我还强烈建议不要将完整的 <video> 标记保存到您的数据库中,而是将其添加到您实际想要显示视频的页面。

示例:

<?php
$result = $conn->query('SELECT ...');
if ($result->num_rows > 0) {
    while($row = $result->fetch_assoc()) {
        ?>
        <video src="<?php echo $row['video-column-path']; ?>"</video>
        <?php
    }
} else {
    ?>
    No videos here
    <?php
}
$conn->close();
?>

找到解决方案,现在需要了解如何将生成的缩略图 url 导入视频的数据库字段...

        // Velidate if files exist
        if (!empty(array_filter($_FILES['fileUpload']['name']))) {
            
            // Loop through file items
            foreach($_FILES['fileUpload']['name'] as $title=>$val){
                // Get files upload path
                $fileName        = $_FILES['fileUpload']['name'][$title];
                $tempLocation    = $_FILES['fileUpload']['tmp_name'][$title];
                $targetFilePath  = $uploadsDir . $fileName;
                $fileType        = strtolower(pathinfo($targetFilePath, PATHINFO_EXTENSION));
                $withOutExtension = pathinfo($fileName, PATHINFO_FILENAME);
                $uploadDate      = date('Y-m-d H:i:s');
                $uploadOk = 1;
                $randomID = rand(1000, 999999);
//Get one thumbnail from the video
        $ffmpeg = "C:\ffmpeg\bin\ffmpeg";
        //echo $ffmpeg;
        $imageFile = 'pic/thumb_'.time().'_'.$randomID.'.jpg';
        $size = "120x90";
        $getFromSecond = 1;


  echo $cmd = "$ffmpeg -i $tempLocation -an -ss $getFromSecond -s $size $imageFile";

  echo "<br>";
  if(!shell_exec($cmd)){
   echo "Thumbnail Created!";
  }else{
   echo "Error creating Thumbnail";
  }