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

(图片来源网络,侵删)
我们必须使用现代的、基于开放标准的Web API来实现这个功能,最核心的技术是 MediaDevices.getUserMedia() API,它可以访问用户的摄像头和麦克风。
下面我将为你提供一个完整的、基于现代Web技术的解决方案,这个方案可以完美地替代你所说的“PHP在线网页flash录制视频”。
核心技术栈
- 前端:
- HTML5: 用于构建页面结构和视频元素。
- JavaScript (ES6+): 用于调用浏览器API,控制摄像头、录制视频流、处理录制数据。
- MediaRecorder API: 这是浏览器内置的API,专门用于录制媒体流。
- 后端:
- PHP: 接收从前端上传的视频Blob数据,并将其保存为服务器上的文件。
- FFmpeg (可选但强烈推荐): 一个强大的命令行工具,可以用来处理录制的视频,例如转换格式(如从
.webm转为.mp4)、调整分辨率、添加水印等。
实现步骤详解
我们将分三步走:
- 前端录制页面: 创建一个允许用户开启摄像头、预览、开始/停止录制,并上传视频的网页。
- 后端PHP处理: 创建一个PHP脚本,用于接收前端上传的视频文件并保存。
- (进阶) 视频格式转换: 使用FFmpeg将录制的
.webm文件转换为更通用的.mp4格式。
第1步:前端录制页面 (record.html)
这个页面将包含所有必要的HTML、CSS和JavaScript代码。

(图片来源网络,侵删)
<!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);
}
?>
如何使用:
- 将
record.html和upload.php放在你的Web服务器(如Apache, Nginx)的同一个目录下。 - 确保服务器有PHP环境。
- 创建一个名为
uploads的目录,并给它设置可写权限(在Linux上通常是chmod 777 uploads,但为了安全,更推荐chown www-data:www-data uploads && chmod 755 uploads)。 - 通过浏览器访问
record.html,你就可以开始录制和上传了。
第3步:(进阶) 使用FFmpeg进行视频转换
浏览器录制的视频通常是 .webm 格式,兼容性很好,但有时你可能需要 .mp4 格式,这时,FFmpeg就派上用场了。
安装FFmpeg:

(图片来源网络,侵删)
- 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,你可以直接使用上面的代码搭建一个功能完整的在线视频录制系统。
