Flash技术(Adobe Flash)已经于2025年12月31日正式被所有主流浏览器停止支持无法在现代浏览器中使用Flash来实现视频录制功能

PHP在线网页flash录制视频
(图片来源网络,侵删)

我们必须使用现代的、基于开放标准的Web API来实现这个功能,最核心的技术是 MediaDevices.getUserMedia() API,它可以访问用户的摄像头和麦克风。

下面我将为你提供一个完整的、基于现代Web技术的解决方案,这个方案可以完美地替代你所说的“PHP在线网页flash录制视频”。


核心技术栈

  1. 前端:
    • HTML5: 用于构建页面结构和视频元素。
    • JavaScript (ES6+): 用于调用浏览器API,控制摄像头、录制视频流、处理录制数据。
    • MediaRecorder API: 这是浏览器内置的API,专门用于录制媒体流。
  2. 后端:
    • PHP: 接收从前端上传的视频Blob数据,并将其保存为服务器上的文件。
    • FFmpeg (可选但强烈推荐): 一个强大的命令行工具,可以用来处理录制的视频,例如转换格式(如从 .webm 转为 .mp4)、调整分辨率、添加水印等。

实现步骤详解

我们将分三步走:

  1. 前端录制页面: 创建一个允许用户开启摄像头、预览、开始/停止录制,并上传视频的网页。
  2. 后端PHP处理: 创建一个PHP脚本,用于接收前端上传的视频文件并保存。
  3. (进阶) 视频格式转换: 使用FFmpeg将录制的 .webm 文件转换为更通用的 .mp4 格式。

第1步:前端录制页面 (record.html)

这个页面将包含所有必要的HTML、CSS和JavaScript代码。

PHP在线网页flash录制视频
(图片来源网络,侵删)
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">在线视频录制</title>
    <style>
        body { font-family: Arial, sans-serif; text-align: center; margin-top: 20px; }
        video, #preview { border: 1px solid #ccc; margin: 10px; background: #f0f0f0; }
        button { padding: 10px 20px; margin: 5px; font-size: 16px; cursor: pointer; }
        #status { margin: 10px 0; font-weight: bold; }
    </style>
</head>
<body>
    <h1>在线视频录制</h1>
    <div id="status">请点击“开启摄像头”开始</div>
    <video id="camera-preview" width="640" height="480" autoplay muted playsinline></video>
    <video id="preview" width="640" height="480" controls></video>
    <div>
        <button id="start-camera">开启摄像头</button>
        <button id="start-record" disabled>开始录制</button>
        <button id="stop-record" disabled>停止录制</button>
    </div>
    <script>
        const cameraPreview = document.getElementById('camera-preview');
        const previewVideo = document.getElementById('preview');
        const startCameraBtn = document.getElementById('start-camera');
        const startRecordBtn = document.getElementById('start-record');
        const stopRecordBtn = document.getElementById('stop-record');
        const statusDiv = document.getElementById('status');
        let mediaRecorder;
        let recordedChunks = [];
        // 1. 开启摄像头
        startCameraBtn.addEventListener('click', async () => {
            try {
                const stream = await navigator.mediaDevices.getUserMedia({ 
                    video: { width: 640, height: 480 }, 
                    audio: true 
                });
                cameraPreview.srcObject = stream;
                startCameraBtn.disabled = true;
                startRecordBtn.disabled = false;
                statusDiv.textContent = '摄像头已开启,可以开始录制了。';
            } catch (err) {
                console.error('无法访问摄像头:', err);
                statusDiv.textContent = '错误: 无法访问摄像头,请确保您已授予权限。';
            }
        });
        // 2. 开始录制
        startRecordBtn.addEventListener('click', () => {
            // 从video元素获取媒体流
            const stream = cameraPreview.srcObject;
            recordedChunks = [];
            // 创建MediaRecorder实例
            mediaRecorder = new MediaRecorder(stream, {
                mimeType: 'video/webm;codecs=vp9,opus' // 尝试使用更优的编码
            });
            mediaRecorder.ondataavailable = (event) => {
                if (event.data.size > 0) {
                    recordedChunks.push(event.data);
                }
            };
            mediaRecorder.onstop = () => {
                // 录制停止,处理数据
                const blob = new Blob(recordedChunks, { type: 'video/webm' });
                const url = URL.createObjectURL(blob);
                previewVideo.src = url;
                // 准备上传
                const formData = new FormData();
                formData.append('video_file', blob, 'recording.webm');
                // 上传到PHP服务器
                uploadVideo(formData);
                statusDiv.textContent = '录制完成,视频已生成并上传。';
            };
            mediaRecorder.start();
            startRecordBtn.disabled = true;
            stopRecordBtn.disabled = false;
            statusDiv.textContent = '正在录制中...';
        });
        // 3. 停止录制
        stopRecordBtn.addEventListener('click', () => {
            mediaRecorder.stop();
            mediaRecorder.stream.getTracks().forEach(track => track.stop()); // 关闭摄像头轨道
            startCameraBtn.disabled = false;
            startRecordBtn.disabled = true;
            stopRecordBtn.disabled = true;
        });
        // 4. 上传视频到PHP
        function uploadVideo(formData) {
            const uploadUrl = 'upload.php'; // 后端处理脚本
            const xhr = new XMLHttpRequest();
            xhr.open('POST', uploadUrl, true);
            xhr.upload.onprogress = (event) => {
                if (event.lengthComputable) {
                    const percentComplete = (event.loaded / event.total) * 100;
                    statusDiv.textContent = `上传中... ${Math.round(percentComplete)}%`;
                }
            };
            xhr.onload = () => {
                if (xhr.status === 200) {
                    statusDiv.textContent = '上传成功!文件已保存到服务器。';
                    console.log('服务器响应:', xhr.responseText);
                } else {
                    statusDiv.textContent = '上传失败,服务器错误。';
                    console.error('上传失败:', xhr.statusText);
                }
            };
            xhr.onerror = () => {
                statusDiv.textContent = '上传失败,网络错误。';
                console.error('网络错误');
            };
            xhr.send(formData);
        }
    </script>
</body>
</html>

第2步:后端PHP处理 (upload.php)

这个脚本负责接收前端上传的文件,并将其保存到服务器的指定目录。

<?php
// 设置响应头为JSON,方便前端处理
header('Content-Type: application/json');
// 定义上传目录,确保此目录存在且可写
$uploadDir = 'uploads/';
// 检查目录是否存在,如果不存在则创建
if (!is_dir($uploadDir)) {
    mkdir($uploadDir, 0777, true);
}
// 检查是否有文件上传
if (isset($_FILES['video_file']) && $_FILES['video_file']['error'] === UPLOAD_ERR_OK) {
    $fileName = $_FILES['video_file']['name'];
    $tmpFilePath = $_FILES['video_file']['tmp_name'];
    // 为了避免文件名冲突,可以生成一个唯一的文件名
    $newFileName = uniqid('recording_', true) . '.webm';
    $destPath = $uploadDir . $newFileName;
    // 移动上传的文件到指定目录
    if (move_uploaded_file($tmpFilePath, $destPath)) {
        // 上传成功
        $response = [
            'success' => true,
            'message' => '文件上传成功!',
            'file_path' => $destPath,
            'file_url' => 'http://' . $_SERVER['HTTP_HOST'] . dirname($_SERVER['REQUEST_URI']) . '/' . $destPath
        ];
        echo json_encode($response);
    } else {
        // 上传失败
        $response = [
            'success' => false,
            'message' => '错误:无法移动文件到上传目录,请检查目录权限。'
        ];
        echo json_encode($response);
    }
} else {
    // 没有文件上传或上传出错
    $errorMessages = [
        UPLOAD_ERR_INI_SIZE => '上传的文件超过了 php.ini 中 upload_max_filesize 指令限制。',
        UPLOAD_ERR_FORM_SIZE => '上传文件的大小超过了 HTML 表单中指定的 MAX_FILE_SIZE 限制。',
        UPLOAD_ERR_PARTIAL => '文件只有部分被上传。',
        UPLOAD_ERR_NO_FILE => '没有文件被上传。',
        // 其他错误码...
    ];
    $errorMessage = isset($_FILES['video_file']['error']) ? $errorMessages[$_FILES['video_file']['error']] : '未知上传错误。';
    $response = [
        'success' => false,
        'message' => '上传失败:' . $errorMessage
    ];
    echo json_encode($response);
}
?>

如何使用:

  1. record.htmlupload.php 放在你的Web服务器(如Apache, Nginx)的同一个目录下。
  2. 确保服务器有PHP环境。
  3. 创建一个名为 uploads 的目录,并给它设置可写权限(在Linux上通常是 chmod 777 uploads,但为了安全,更推荐 chown www-data:www-data uploads && chmod 755 uploads)。
  4. 通过浏览器访问 record.html,你就可以开始录制和上传了。

第3步:(进阶) 使用FFmpeg进行视频转换

浏览器录制的视频通常是 .webm 格式,兼容性很好,但有时你可能需要 .mp4 格式,这时,FFmpeg就派上用场了。

安装FFmpeg:

PHP在线网页flash录制视频
(图片来源网络,侵删)
  • Linux (Ubuntu/Debian): sudo apt-get update && sudo apt-get install ffmpeg
  • macOS (Homebrew): brew install ffmpeg
  • Windows: 从 FFmpeg官网 下载并配置环境变量。

修改PHP脚本 (`upload.php``) 以进行转换:

<?php
// ... (前面的代码保持不变) ...
if (move_uploaded_file($tmpFilePath, $destPath)) {
    // --- 新增的FFmpeg转换代码 ---
    $mp4DestPath = $uploadDir . pathinfo($newFileName, PATHINFO_FILENAME) . '.mp4';
    $ffmpegCommand = "ffmpeg -i \"{$destPath}\" -c:v libx264 -c:a aac -movflags +faststart \"{$mp4DestPath}\" 2>&1";
    // 执行FFmpeg命令
    exec($ffmpegCommand, $output, $return_var);
    if ($return_var === 0) {
        // 转换成功,可以删除原始的webm文件以节省空间
        unlink($destPath);
        $finalFilePath = $mp4DestPath;
        $fileExtension = 'mp4';
    } else {
        // 转换失败,使用原始webm文件
        $finalFilePath = $destPath;
        $fileExtension = 'webm';
        error_log("FFmpeg conversion failed. Command: " . $ffmpegCommand . "\nOutput: " . implode("\n", $output));
    }
    // --- 转换代码结束 ---
    $response = [
        'success' => true,
        'message' => '文件上传并处理成功!',
        'file_path' => $finalFilePath,
        'file_url' => 'http://' . $_SERVER['HTTP_HOST'] . dirname($_SERVER['REQUEST_URI']) . '/' . $finalFilePath,
        'file_type' => $fileExtension
    ];
    echo json_encode($response);
} else {
    // ... (后面的代码保持不变) ...
}
?>

注意:

  • exec() 函数在PHP中默认可能是禁用的,你需要在 php.ini 中启用它 (disable_functions 中删除 exec)。
  • 执行系统命令有安全风险,请确保你的输入是可信的,在这个例子中,文件名是系统生成的,所以是安全的。
  • -movflags +faststart 对于网络流播放非常重要,它可以将视频的元数据移到文件开头,这样浏览器可以边下载边播放。
功能 Flash (已淘汰) 现代Web方案
核心API NetStream, Camera navigator.mediaDevices.getUserMedia(), MediaRecorder
前端 ActionScript 3.0 HTML5, JavaScript (ES6+)
后端 AMF, RTMP/FLV PHP接收Blob/FormData文件上传
视频格式 FLV, MP4 (通过FMS) WebM (原生支持), MP4 (通过FFmpeg转换)
兼容性 极差,仅限旧版浏览器/插件 非常好,所有现代浏览器都支持

这个现代Web方案不仅完全取代了Flash的功能,而且在性能、兼容性、安全性方面都远超Flash,你可以直接使用上面的代码搭建一个功能完整的在线视频录制系统。