如何在 Web 应用程序中实现类似 YouTube 的视频播放?

How to achive YouTube-like Video Playback in Web Apps?

提问人:SNAV 提问时间:11/16/2023 更新时间:11/16/2023 访问量:21

问:

我的视频平台目前在开始播放之前会一次性加载所有视频内容。我怎样才能让它在用户观看视频时以更小的块加载视频,就像 YouTube 所做的那样?

<div class="main_video_player">
  <video controls width="100%" height="auto" poster="<?php echo $thumbnail_path; ?>" data-src="<?php echo $video_url; ?>">
    <source src="<?php echo $video_url; ?>" type="video/mp4">
    Your browser does not support the video tag.
  </video>
</div>

它一次加载整个视频,然后开始播放视频,这是主要问题。 我希望视频立即开始播放。以下是视频存储的代码:

<?php
require_once('../config.php');

// Function to generate a random video ID (link)
function generate_random_id($length = 10) {
    $characters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
    $random_id = '';
    for ($i = 0; $i < $length; $i++) {
        $random_id .= $characters[rand(0, strlen($characters) - 1)];
    }
    return $random_id;
}

// Function to check if the generated video_id exists in the database
function is_video_id_exists($video_id, $conn) {
    $sql = "SELECT COUNT(*) as count FROM videos WHERE video_id = ?";
    $stmt = $conn->prepare($sql);
    $stmt->bind_param("s", $video_id);
    $stmt->execute();
    $result = $stmt->get_result();
    $row = $result->fetch_assoc();
    $count = $row['count'];
    $stmt->close();
    return $count > 0;
}
// Function to send video content with byte range support
function send_video_content($video_url) {
    header('Accept-Ranges: bytes');
    header('Content-Type: video/mp4');

    $video_file_size = filesize($video_url);

    if (isset($_SERVER['HTTP_RANGE'])) {
        list($size_unit, $range) = explode('=', $_SERVER['HTTP_RANGE'], 2);
        if ($size_unit === 'bytes') {
            list($range_start, $range_end) = explode('-', $range, 2);
            $range_start = intval($range_start);
            $range_end = intval($range_end);
        }
    } else {
        $range_start = 0;
        $range_end = $video_file_size - 1;
    }

    header('HTTP/1.1 206 Partial Content');
    header('Content-Length: ' . ($range_end - $range_start + 1));
    header("Content-Range: bytes $range_start-$range_end/$video_file_size");

    $video_file = fopen($video_url, 'rb');
    fseek($video_file, $range_start);
    echo fread($video_file, $range_end - $range_start + 1);
    fclose($video_file);
}

if ($_SERVER["REQUEST_METHOD"] == "POST") {
    // Validate form data
    if (isset($_POST["title"]) && isset($_POST["category"]) && isset($_FILES["video_file"]) && isset($_POST["thumbnail_data"])) {
        $title = $_POST["title"];
        $category = $_POST["category"];
        $user_ip = $_SERVER["REMOTE_ADDR"];

        // Generate a random video ID (link)
        $video_id = generate_random_id(10);

        // Check if the generated video_id already exists in the database
        
        while (is_video_id_exists($video_id, $conn)) {
            $video_id = generate_random_id(10);
        }

        // File upload handling for video
        $target_dir = "../uploads/";
        $video_filename = $video_id . ".mp4";
        $video_url = $target_dir . $video_filename;
        $uploadOk = 1;
        $videoFileType = strtolower(pathinfo($_FILES["video_file"]["name"], PATHINFO_EXTENSION));

        // Check if the video file is valid
        $maxFileSize = 500 * 1024 * 1024; // 500 MB in bytes

        if ($_FILES["video_file"]["size"] > $maxFileSize) {
            echo "Error: Video file is too large. Maximum file size is 500 MB.";
            $uploadOk = 0;
        }

        // Allow only specific video file formats (you can add more if needed)
        if ($videoFileType !== "mp4" && $videoFileType !== "avi" && $videoFileType !== "mov") {
            echo "Error: Only MP4, AVI, and MOV video formats are allowed.";
            $uploadOk = 0;
        }

        // If the file upload is valid, move the video to the uploads folder
        if ($uploadOk) {
            if (move_uploaded_file($_FILES["video_file"]["tmp_name"], $video_url)) {
                // Get the thumbnail data
                $thumbnail_data = $_POST["thumbnail_data"];

                // Decode the base64-encoded thumbnail data
                $thumbnail_data_decoded = base64_decode(str_replace('data:image/jpeg;base64,', '', $thumbnail_data));

                // Generate a random filename for the thumbnail
                $thumbnail_filename = generate_random_id(10) . ".jpg";

                // Set the path to save the thumbnail on the server
                $thumbnail_path = "../thumbnails/" . $thumbnail_filename;

                // Create an image resource from the decoded thumbnail data
                $thumbnail = imagecreatefromstring($thumbnail_data_decoded);

                // Set the desired thumbnail width and height (e.g., 200x200)
                $thumbnail_width = 640;
                $thumbnail_height = 360;

                // Create a new thumbnail with the desired size using GD library
                $thumbnail_resized = imagescale($thumbnail, $thumbnail_width, $thumbnail_height);

                // Save the resized thumbnail to the server with a lower quality setting
                imagejpeg($thumbnail_resized, $thumbnail_path, 80); 

                // Free up memory
                imagedestroy($thumbnail);
                imagedestroy($thumbnail_resized);

                // Prepare and execute the SQL query to save video and thumbnail information
                $stmt = $conn->prepare("INSERT INTO videos (video_id, title, category, video_url, thumbnail_url, user_ip) VALUES (?, ?, ?, ?, ?, ?)");
                $stmt->bind_param("ssssss", $video_id, $title, $category, $video_filename, $thumbnail_filename, $user_ip);

                if ($stmt->execute()) {
                    // Insertion successful, create the video link
                    $video_link = "http://localhost/new/hub/#/video?video_id=" . $video_id;

                    // Construct the response data as an associative array
                    $response = array(
                        'success' => true,
                        'message' => "Video uploaded complete",
                        'video_link' => $video_link,
                        'category' => $category, // Include category in the response
                        'thumbnail_url' => $thumbnail_filename,
                    );

                    
                    header('Content-Type: application/json');

                    // Send the JSON response
                    echo json_encode($response);
                    exit();
                } else {
                    echo "Error: " . $stmt->error;
                }

                $stmt->close();
            } else {
                echo "Error: Failed to upload the video.";
            }
        }
    } else {
        echo "Error: Missing form fields!";
    }
}


$conn->close();
?>

文件上传 HTML5-视频 加载

评论

0赞 VC.One 11/18/2023
您的 MP4 似乎有它的元数据,称为 MOOV 框,放在文件的后面(所以它现在必须完全下载才能播放)。MOOV告诉视频播放器哪些字节是第一帧的字节,等等。要修复,您需要一个工具。在 Google 上搜索关键字。或者,如果您知道的话,请使用 FFmpeg。mp4 moov front fix
0赞 VC.One 11/18/2023
PS:如果这是我的问题,我会下载 FFmpeg,然后用它来制作一个碎片化的 MP4(它可以是一个长文件或单独的块)。那么现在查找意味着只获取(或)最接近请求的查找时间的块的字节。echo

答: 暂无答案