事件处理
本章将详细介绍videojs-record提供的所有事件及其处理方法,帮助您更好地响应录制过程中的各种状态变化。
11.1 设备相关事件
设备相关事件在媒体设备状态变化时触发:
事件名 | 触发时机 | 参数 | 说明 |
---|---|---|---|
deviceReady | 设备准备就绪 | 无 | 设备已成功初始化并可以开始录制 |
deviceError | 设备发生错误 | error: Error对象 | 设备初始化或使用过程中发生错误 |
loadDevice | 设备加载完成 | 无 | 设备加载完成后触发 |
startDevice | 设备开始工作 | 无 | 设备开始捕获媒体流时触发 |
设备事件处理示例
// 监听设备就绪事件
player.on('deviceReady', function() {
console.log('设备已就绪');
updateUI('设备就绪,可以开始录制');
});
// 监听设备错误事件
player.on('deviceError', function(event, error) {
console.error('设备错误:', error);
updateUI('设备错误: ' + error.name);
// 根据错误类型进行处理
switch(error.name) {
case 'NotAllowedError':
showMessage('请允许访问摄像头和麦克风');
break;
case 'NotFoundError':
showMessage('未找到摄像头或麦克风设备');
break;
case 'NotReadableError':
showMessage('设备被其他应用占用');
break;
default:
showMessage('设备访问失败');
}
});
// 监听设备加载事件
player.on('loadDevice', function() {
console.log('设备加载完成');
});
// 监听设备开始事件
player.on('startDevice', function() {
console.log('设备开始工作');
updateUI('设备正在工作中...');
});
// 更新UI状态
function updateUI(status) {
const statusElement = document.getElementById('deviceStatus');
if (statusElement) {
statusElement.textContent = status;
}
}
// 显示消息
function showMessage(message) {
const messageElement = document.getElementById('message');
if (messageElement) {
messageElement.textContent = message;
messageElement.style.display = 'block';
// 3秒后隐藏消息
setTimeout(() => {
messageElement.style.display = 'none';
}, 3000);
}
}
11.2 录制状态事件
录制状态事件在录制过程状态变化时触发:
事件名 | 触发时机 | 参数 | 说明 |
---|---|---|---|
startRecord | 开始录制 | 无 | 录制开始时触发 |
stopRecord | 停止录制 | 无 | 录制停止时触发 |
pauseRecord | 暂停录制 | 无 | 录制暂停时触发 |
resumeRecord | 恢复录制 | 无 | 录制恢复时触发 |
finishRecord | 录制完成 | 无 | 录制数据处理完成后触发 |
录制状态事件处理示例
// 监听开始录制事件
player.on('startRecord', function() {
console.log('开始录制');
updateRecordingStatus('正在录制...');
// 禁用开始按钮,启用暂停和停止按钮
toggleRecordingButtons(true, false, false);
});
// 监听停止录制事件
player.on('stopRecord', function() {
console.log('停止录制');
updateRecordingStatus('录制已停止');
// 启用开始按钮,禁用暂停和停止按钮
toggleRecordingButtons(false, true, true);
});
// 监听暂停录制事件
player.on('pauseRecord', function() {
console.log('暂停录制');
updateRecordingStatus('录制已暂停');
// 启用恢复按钮,禁用暂停按钮
toggleRecordingButtons(false, true, false);
});
// 监听恢复录制事件
player.on('resumeRecord', function() {
console.log('恢复录制');
updateRecordingStatus('正在录制...');
// 启用暂停按钮,禁用恢复按钮
toggleRecordingButtons(true, false, false);
});
// 监听录制完成事件
player.on('finishRecord', function() {
console.log('录制完成');
updateRecordingStatus('录制完成');
// 处理录制的数据
handleRecordedData();
// 启用开始按钮,禁用暂停和停止按钮
toggleRecordingButtons(false, true, true);
});
// 更新录制状态
function updateRecordingStatus(status) {
const statusElement = document.getElementById('recordingStatus');
if (statusElement) {
statusElement.textContent = status;
}
}
// 切换录制按钮状态
function toggleRecordingButtons(startDisabled, pauseDisabled, stopDisabled) {
const startBtn = document.getElementById('startBtn');
const pauseBtn = document.getElementById('pauseBtn');
const stopBtn = document.getElementById('stopBtn');
if (startBtn) startBtn.disabled = startDisabled;
if (pauseBtn) pauseBtn.disabled = pauseDisabled;
if (stopBtn) stopBtn.disabled = stopDisabled;
}
// 处理录制的数据
function handleRecordedData() {
const data = player.recordedData;
if (data && data.video) {
// 显示录制的视频
displayRecordedVideo(data.video);
// 提供下载选项
enableDownloadOption(data.video);
// 可选:上传到服务器
// uploadRecordedData(data);
}
}
// 显示录制的视频
function displayRecordedVideo(videoBlob) {
const videoUrl = URL.createObjectURL(videoBlob);
const videoElement = document.getElementById('recordedVideo');
if (videoElement) {
videoElement.src = videoUrl;
videoElement.style.display = 'block';
}
}
// 启用下载选项
function enableDownloadOption(videoBlob) {
const downloadBtn = document.getElementById('downloadBtn');
if (downloadBtn) {
downloadBtn.onclick = function() {
const a = document.createElement('a');
a.href = URL.createObjectURL(videoBlob);
a.download = 'recording-' + new Date().getTime() + '.webm';
a.click();
};
downloadBtn.style.display = 'inline-block';
}
}
11.3 数据相关事件
数据相关事件在录制数据处理过程中触发:
事件名 | 触发时机 | 参数 | 说明 |
---|---|---|---|
dataAvailable | 数据可用 | data: Blob对象 | 时间切片录制时每个数据块可用时触发 |
progressRecord | 录制进度 | progress: 进度信息 | 录制进度更新时触发 |
timestamp | 时间戳更新 | timestamp: 时间戳 | 录制时间戳更新时触发 |
数据事件处理示例
// 监听数据可用事件(时间切片录制)
player.on('dataAvailable', function(event, data) {
console.log('数据可用:', data);
// 处理时间切片数据
handleTimeSliceData(data);
});
// 监听录制进度事件
player.on('progressRecord', function(event, progress) {
console.log('录制进度:', progress);
// 更新进度条
updateProgressBar(progress);
// 更新录制时间显示
updateRecordingTime(progress);
});
// 监听时间戳更新事件
player.on('timestamp', function(event, timestamp) {
console.log('时间戳更新:', timestamp);
// 更新时间显示
updateTimeDisplay(timestamp);
});
// 处理时间切片数据
function handleTimeSliceData(data) {
// 实时上传数据块
uploadTimeSlice(data);
// 或者保存到本地存储
// saveTimeSliceLocally(data);
}
// 实时上传时间切片
function uploadTimeSlice(data) {
const formData = new FormData();
formData.append('video', data.video, 'slice-' + Date.now() + '.webm');
fetch('/upload-timeslice', {
method: 'POST',
body: formData
})
.then(response => response.json())
.then(result => {
console.log('时间切片上传成功:', result);
})
.catch(error => {
console.error('时间切片上传失败:', error);
});
}
// 更新进度条
function updateProgressBar(progress) {
const progressBar = document.getElementById('progressBar');
if (progressBar) {
const percentage = (progress.current / progress.total) * 100;
progressBar.style.width = percentage + '%';
progressBar.textContent = Math.round(percentage) + '%';
}
}
// 更新录制时间显示
function updateRecordingTime(progress) {
const timeElement = document.getElementById('recordingTime');
if (timeElement) {
const currentTime = formatTime(progress.current);
const totalTime = formatTime(progress.total);
timeElement.textContent = currentTime + ' / ' + totalTime;
}
}
// 更新时间显示
function updateTimeDisplay(timestamp) {
const timestampElement = document.getElementById('timestamp');
if (timestampElement) {
timestampElement.textContent = formatTime(timestamp);
}
}
// 格式化时间显示
function formatTime(seconds) {
const mins = Math.floor(seconds / 60);
const secs = Math.floor(seconds % 60);
return mins.toString().padStart(2, '0') + ':' + secs.toString().padStart(2, '0');
}
11.4 屏幕录制事件
屏幕录制特有的事件:
事件名 | 触发时机 | 参数 | 说明 |
---|---|---|---|
startScreenShare | 开始屏幕共享 | 无 | 屏幕共享开始时触发 |
stopScreenShare | 停止屏幕共享 | 无 | 屏幕共享停止时触发 |
screenError | 屏幕录制错误 | error: Error对象 | 屏幕录制过程中发生错误时触发 |
屏幕录制事件处理示例
// 监听开始屏幕共享事件
player.on('startScreenShare', function() {
console.log('开始屏幕共享');
updateScreenShareStatus('正在共享屏幕...');
});
// 监听停止屏幕共享事件
player.on('stopScreenShare', function() {
console.log('停止屏幕共享');
updateScreenShareStatus('屏幕共享已停止');
});
// 监听屏幕录制错误事件
player.on('screenError', function(event, error) {
console.error('屏幕录制错误:', error);
updateScreenShareStatus('屏幕共享错误: ' + error.message);
// 根据错误类型处理
handleScreenShareError(error);
});
// 更新屏幕共享状态
function updateScreenShareStatus(status) {
const statusElement = document.getElementById('screenShareStatus');
if (statusElement) {
statusElement.textContent = status;
}
}
// 处理屏幕共享错误
function handleScreenShareError(error) {
switch(error.name) {
case 'NotAllowedError':
showMessage('用户拒绝了屏幕共享请求');
break;
case 'NotFoundError':
showMessage('未找到可共享的屏幕');
break;
case 'NotSupportedError':
showMessage('浏览器不支持屏幕共享功能');
break;
default:
showMessage('屏幕共享失败: ' + error.message);
}
}
// 显示消息
function showMessage(message) {
const messageElement = document.getElementById('message');
if (messageElement) {
messageElement.textContent = message;
messageElement.className = 'error-message';
messageElement.style.display = 'block';
// 5秒后隐藏消息
setTimeout(() => {
messageElement.style.display = 'none';
}, 5000);
}
}
11.5 事件移除和管理
正确管理事件监听器的添加和移除:
事件管理示例
// 事件管理器类
class EventManager {
constructor(player) {
this.player = player;
this.listeners = new Map();
}
// 添加事件监听器
addEventListener(eventName, handler) {
// 存储监听器引用
if (!this.listeners.has(eventName)) {
this.listeners.set(eventName, []);
}
this.listeners.get(eventName).push(handler);
// 添加事件监听器
this.player.on(eventName, handler);
console.log('添加事件监听器:', eventName);
}
// 移除事件监听器
removeEventListener(eventName, handler) {
// 移除事件监听器
this.player.off(eventName, handler);
// 从存储中移除引用
if (this.listeners.has(eventName)) {
const handlers = this.listeners.get(eventName);
const index = handlers.indexOf(handler);
if (index > -1) {
handlers.splice(index, 1);
}
}
console.log('移除事件监听器:', eventName);
}
// 移除所有事件监听器
removeAllEventListeners() {
for (const [eventName, handlers] of this.listeners) {
handlers.forEach(handler => {
this.player.off(eventName, handler);
});
}
this.listeners.clear();
console.log('移除所有事件监听器');
}
// 获取事件监听器数量
getListenerCount(eventName) {
if (this.listeners.has(eventName)) {
return this.listeners.get(eventName).length;
}
return 0;
}
}
// 创建事件管理器
const eventManager = new EventManager(player);
// 添加事件监听器
const deviceReadyHandler = function() {
console.log('设备就绪');
};
eventManager.addEventListener('deviceReady', deviceReadyHandler);
const startRecordHandler = function() {
console.log('开始录制');
};
eventManager.addEventListener('startRecord', startRecordHandler);
// 移除特定事件监听器
// eventManager.removeEventListener('deviceReady', deviceReadyHandler);
// 移除所有事件监听器
// eventManager.removeAllEventListeners();
// 获取监听器数量
console.log('deviceReady监听器数量:', eventManager.getListenerCount('deviceReady'));
提示:在页面卸载或组件销毁时,记得移除事件监听器以避免内存泄漏。