事件处理

本章将详细介绍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'));

提示:在页面卸载或组件销毁时,记得移除事件监听器以避免内存泄漏。