Search K
Appearance
Appearance
关键词: HTML5视频元素, video标签, 视频格式, 视频播放, 视频控制, 视频字幕, 视频轨道, 自定义播放器, 视频优化
HTML5的<video>元素为网页提供了原生的视频播放功能,无需依赖Flash等插件。
<video src="video.mp4" controls>
您的浏览器不支持video标签
</video><!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>HTML5 视频元素示例</title>
<style>
body {
font-family: 'Microsoft YaHei', Arial, sans-serif;
max-width: 800px;
margin: 0 auto;
padding: 20px;
background-color: #f5f5f5;
}
.video-container {
background: white;
padding: 20px;
border-radius: 10px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
margin-bottom: 20px;
}
.video-container h3 {
color: #333;
margin-bottom: 15px;
border-bottom: 2px solid #007bff;
padding-bottom: 10px;
}
video {
width: 100%;
max-width: 640px;
border-radius: 8px;
box-shadow: 0 4px 8px rgba(0,0,0,0.2);
}
.video-info {
margin-top: 15px;
padding: 10px;
background-color: #e9ecef;
border-radius: 5px;
}
.controls-demo {
margin-top: 20px;
}
.button-group {
margin-top: 10px;
}
button {
background-color: #007bff;
color: white;
border: none;
padding: 8px 16px;
margin: 5px;
border-radius: 5px;
cursor: pointer;
transition: background-color 0.3s;
}
button:hover {
background-color: #0056b3;
}
button:disabled {
background-color: #6c757d;
cursor: not-allowed;
}
.volume-control {
margin-top: 10px;
}
input[type="range"] {
width: 200px;
margin: 0 10px;
}
.progress-bar {
width: 100%;
height: 6px;
background-color: #ddd;
border-radius: 3px;
margin: 10px 0;
overflow: hidden;
}
.progress-fill {
height: 100%;
background-color: #007bff;
width: 0%;
transition: width 0.1s;
}
.time-display {
display: flex;
justify-content: space-between;
font-size: 14px;
color: #666;
}
</style>
</head>
<body>
<h1>HTML5 视频元素详解</h1>
<!-- 基本视频播放器 -->
<div class="video-container">
<h3>1. 基本视频播放器</h3>
<video controls id="basicVideo">
<source src="https://www.w3schools.com/html/mov_bbb.mp4" type="video/mp4">
<source src="https://www.w3schools.com/html/mov_bbb.ogg" type="video/ogg">
您的浏览器不支持视频标签
</video>
<div class="video-info">
<p><strong>特点:</strong>使用浏览器原生控件,支持多种格式</p>
</div>
</div>
<!-- 自动播放静音视频 -->
<div class="video-container">
<h3>2. 自动播放静音视频</h3>
<video autoplay muted loop id="autoplayVideo">
<source src="https://www.w3schools.com/html/mov_bbb.mp4" type="video/mp4">
您的浏览器不支持视频标签
</video>
<div class="video-info">
<p><strong>特点:</strong>自动播放、静音、循环播放</p>
<p><strong>注意:</strong>现代浏览器要求自动播放视频必须静音</p>
</div>
</div>
<!-- 自定义控件视频播放器 -->
<div class="video-container">
<h3>3. 自定义控件视频播放器</h3>
<video id="customVideo" poster="https://via.placeholder.com/640x360/007bff/ffffff?text=Video+Poster">
<source src="https://www.w3schools.com/html/mov_bbb.mp4" type="video/mp4">
您的浏览器不支持视频标签
</video>
<div class="controls-demo">
<div class="progress-bar" id="progressBar">
<div class="progress-fill" id="progressFill"></div>
</div>
<div class="time-display">
<span id="currentTime">00:00</span>
<span id="totalTime">00:00</span>
</div>
<div class="button-group">
<button onclick="playPause()">播放/暂停</button>
<button onclick="stop()">停止</button>
<button onclick="skipTime(-10)">后退10秒</button>
<button onclick="skipTime(10)">前进10秒</button>
<button onclick="toggleFullscreen()">全屏</button>
</div>
<div class="volume-control">
<label>音量:</label>
<input type="range" min="0" max="1" step="0.1" value="0.5"
onchange="setVolume(this.value)" id="volumeSlider">
<span id="volumeDisplay">50%</span>
<button onclick="toggleMute()">静音</button>
</div>
</div>
<div class="video-info">
<p><strong>当前状态:</strong><span id="videoStatus">未开始</span></p>
<p><strong>播放速度:</strong>
<select onchange="setPlaybackRate(this.value)">
<option value="0.5">0.5x</option>
<option value="1" selected>1x</option>
<option value="1.25">1.25x</option>
<option value="1.5">1.5x</option>
<option value="2">2x</option>
</select>
</p>
</div>
</div>
<!-- 带字幕的视频 -->
<div class="video-container">
<h3>4. 带字幕的视频</h3>
<video controls id="subtitleVideo">
<source src="https://www.w3schools.com/html/mov_bbb.mp4" type="video/mp4">
<track kind="subtitles" src="subtitles.vtt" srclang="zh" label="中文字幕" default>
<track kind="subtitles" src="subtitles-en.vtt" srclang="en" label="English">
您的浏览器不支持视频标签
</video>
<div class="video-info">
<p><strong>特点:</strong>支持多语言字幕切换</p>
</div>
</div>
<!-- 视频事件监听演示 -->
<div class="video-container">
<h3>5. 视频事件监听演示</h3>
<video controls id="eventVideo">
<source src="https://www.w3schools.com/html/mov_bbb.mp4" type="video/mp4">
您的浏览器不支持视频标签
</video>
<div class="video-info">
<p><strong>事件日志:</strong></p>
<div id="eventLog" style="max-height: 200px; overflow-y: auto; background: #f8f9fa; padding: 10px; border-radius: 5px; font-family: monospace; font-size: 12px;"></div>
</div>
</div>
<script>
// 自定义视频播放器相关变量
const customVideo = document.getElementById('customVideo');
const progressBar = document.getElementById('progressBar');
const progressFill = document.getElementById('progressFill');
const currentTimeSpan = document.getElementById('currentTime');
const totalTimeSpan = document.getElementById('totalTime');
const videoStatus = document.getElementById('videoStatus');
const volumeSlider = document.getElementById('volumeSlider');
const volumeDisplay = document.getElementById('volumeDisplay');
// 格式化时间显示
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')}`;
}
// 播放/暂停功能
function playPause() {
if (customVideo.paused) {
customVideo.play();
} else {
customVideo.pause();
}
}
// 停止播放
function stop() {
customVideo.pause();
customVideo.currentTime = 0;
}
// 跳转时间
function skipTime(seconds) {
customVideo.currentTime += seconds;
}
// 设置音量
function setVolume(volume) {
customVideo.volume = volume;
volumeDisplay.textContent = Math.round(volume * 100) + '%';
}
// 切换静音
function toggleMute() {
customVideo.muted = !customVideo.muted;
volumeSlider.value = customVideo.muted ? 0 : customVideo.volume;
volumeDisplay.textContent = customVideo.muted ? '0%' : Math.round(customVideo.volume * 100) + '%';
}
// 设置播放速度
function setPlaybackRate(rate) {
customVideo.playbackRate = parseFloat(rate);
}
// 全屏切换
function toggleFullscreen() {
if (customVideo.requestFullscreen) {
customVideo.requestFullscreen();
} else if (customVideo.webkitRequestFullscreen) {
customVideo.webkitRequestFullscreen();
} else if (customVideo.msRequestFullscreen) {
customVideo.msRequestFullscreen();
}
}
// 更新播放进度
function updateProgress() {
const progress = (customVideo.currentTime / customVideo.duration) * 100;
progressFill.style.width = progress + '%';
currentTimeSpan.textContent = formatTime(customVideo.currentTime);
}
// 点击进度条跳转
progressBar.addEventListener('click', (e) => {
const rect = progressBar.getBoundingClientRect();
const pos = (e.clientX - rect.left) / rect.width;
customVideo.currentTime = pos * customVideo.duration;
});
// 视频事件监听
customVideo.addEventListener('loadedmetadata', () => {
totalTimeSpan.textContent = formatTime(customVideo.duration);
videoStatus.textContent = '已加载';
});
customVideo.addEventListener('play', () => {
videoStatus.textContent = '播放中';
});
customVideo.addEventListener('pause', () => {
videoStatus.textContent = '已暂停';
});
customVideo.addEventListener('timeupdate', updateProgress);
customVideo.addEventListener('ended', () => {
videoStatus.textContent = '播放结束';
});
// 视频事件监听演示
const eventVideo = document.getElementById('eventVideo');
const eventLog = document.getElementById('eventLog');
function logEvent(event) {
const timestamp = new Date().toLocaleTimeString();
const logEntry = `[${timestamp}] ${event.type}: ${event.target.currentTime ? formatTime(event.target.currentTime) : 'N/A'}`;
eventLog.innerHTML += logEntry + '<br>';
eventLog.scrollTop = eventLog.scrollHeight;
}
// 添加各种事件监听
const events = ['loadstart', 'loadedmetadata', 'loadeddata', 'canplay', 'canplaythrough',
'play', 'pause', 'seeking', 'seeked', 'timeupdate', 'ended', 'error'];
events.forEach(event => {
eventVideo.addEventListener(event, logEvent);
});
// 初始化音量显示
setVolume(0.5);
// 键盘快捷键支持
document.addEventListener('keydown', (e) => {
if (e.target.tagName.toLowerCase() === 'video') {
switch(e.key) {
case ' ':
e.preventDefault();
playPause();
break;
case 'ArrowLeft':
e.preventDefault();
skipTime(-5);
break;
case 'ArrowRight':
e.preventDefault();
skipTime(5);
break;
case 'ArrowUp':
e.preventDefault();
customVideo.volume = Math.min(1, customVideo.volume + 0.1);
volumeSlider.value = customVideo.volume;
setVolume(customVideo.volume);
break;
case 'ArrowDown':
e.preventDefault();
customVideo.volume = Math.max(0, customVideo.volume - 0.1);
volumeSlider.value = customVideo.volume;
setVolume(customVideo.volume);
break;
}
}
});
</script>
</body>
</html>不同浏览器对视频格式的支持有所不同,因此需要提供多种格式。
| 格式 | 编码器 | 浏览器支持 | 优缺点 |
|---|---|---|---|
| MP4 | H.264 | Chrome, Firefox, Safari, Edge | 广泛支持,质量好 |
| WebM | VP8/VP9 | Chrome, Firefox, Opera | 开源,压缩率高 |
| OGG | Theora | Firefox, Chrome, Opera | 开源,但支持有限 |
<video controls>
<source src="video.mp4" type="video/mp4">
<source src="video.webm" type="video/webm">
<source src="video.ogv" type="video/ogg">
<p>您的浏览器不支持视频播放</p>
</video><video
src="video.mp4" <!-- 视频源 -->
controls <!-- 显示控件 -->
autoplay <!-- 自动播放 -->
loop <!-- 循环播放 -->
muted <!-- 静音 -->
preload="auto" <!-- 预加载 -->
poster="poster.jpg" <!-- 封面图 -->
width="640" <!-- 宽度 -->
height="360" <!-- 高度 -->
playsinline <!-- 内联播放 -->
crossorigin="anonymous" <!-- 跨域设置 -->
>
您的浏览器不支持视频标签
</video>none: 不预加载metadata: 仅预加载元数据auto: 预加载整个视频// 获取视频元素
const video = document.getElementById('myVideo');
// 播放控制
video.play(); // 播放
video.pause(); // 暂停
video.load(); // 重新加载
// 时间控制
video.currentTime = 30; // 跳转到30秒
video.duration; // 总时长
// 音量控制
video.volume = 0.5; // 设置音量(0-1)
video.muted = true; // 静音
// 播放速度
video.playbackRate = 1.5; // 1.5倍速播放
// 状态检查
video.paused; // 是否暂停
video.ended; // 是否结束
video.readyState; // 准备状态// 创建视频分析器
function createVideoAnalyzer() {
const video = document.getElementById('myVideo');
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
// 设置canvas尺寸
canvas.width = video.videoWidth;
canvas.height = video.videoHeight;
// 实时分析视频帧
function analyzeFrame() {
if (video.readyState === video.HAVE_ENOUGH_DATA) {
ctx.drawImage(video, 0, 0);
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
// 分析图像数据
const data = imageData.data;
let r = 0, g = 0, b = 0;
for (let i = 0; i < data.length; i += 4) {
r += data[i];
g += data[i + 1];
b += data[i + 2];
}
const pixelCount = data.length / 4;
const avgColor = {
r: Math.round(r / pixelCount),
g: Math.round(g / pixelCount),
b: Math.round(b / pixelCount)
};
console.log('平均颜色:', avgColor);
}
requestAnimationFrame(analyzeFrame);
}
video.addEventListener('play', analyzeFrame);
}const video = document.getElementById('myVideo');
// 开始加载
video.addEventListener('loadstart', () => {
console.log('开始加载视频');
});
// 元数据加载完成
video.addEventListener('loadedmetadata', () => {
console.log('视频元数据加载完成');
console.log('视频尺寸:', video.videoWidth, 'x', video.videoHeight);
console.log('视频时长:', video.duration);
});
// 足够数据播放
video.addEventListener('canplay', () => {
console.log('可以开始播放');
});
// 可以流畅播放
video.addEventListener('canplaythrough', () => {
console.log('可以流畅播放');
});// 播放状态
video.addEventListener('play', () => {
console.log('开始播放');
});
video.addEventListener('pause', () => {
console.log('暂停播放');
});
video.addEventListener('ended', () => {
console.log('播放结束');
});
// 时间更新
video.addEventListener('timeupdate', () => {
const progress = (video.currentTime / video.duration) * 100;
console.log('播放进度:', progress.toFixed(2) + '%');
});
// 跳转事件
video.addEventListener('seeking', () => {
console.log('开始跳转');
});
video.addEventListener('seeked', () => {
console.log('跳转完成');
});创建字幕文件 subtitles.vtt:
WEBVTT
00:00:00.000 --> 00:00:05.000
欢迎观看HTML5视频教程
00:00:05.000 --> 00:00:10.000
我们将学习如何使用video元素
00:00:10.000 --> 00:00:15.000
包括各种属性和JavaScript API<video controls>
<source src="video.mp4" type="video/mp4">
<track kind="subtitles" src="subtitles.vtt" srclang="zh" label="中文字幕" default>
<track kind="subtitles" src="subtitles-en.vtt" srclang="en" label="English">
<track kind="chapters" src="chapters.vtt" srclang="zh" label="章节">
<track kind="descriptions" src="descriptions.vtt" srclang="zh" label="音频描述">
</video><style>
.responsive-video {
position: relative;
width: 100%;
height: 0;
padding-bottom: 56.25%; /* 16:9 比例 */
}
.responsive-video video {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
</style>
<div class="responsive-video">
<video controls>
<source src="video.mp4" type="video/mp4">
</video>
</div>async function enablePictureInPicture() {
const video = document.getElementById('myVideo');
try {
if (video.requestPictureInPicture) {
await video.requestPictureInPicture();
}
} catch (error) {
console.error('画中画模式失败:', error);
}
}
// 监听画中画事件
video.addEventListener('enterpictureinpicture', () => {
console.log('进入画中画模式');
});
video.addEventListener('leavepictureinpicture', () => {
console.log('退出画中画模式');
});function generateThumbnail(videoFile, time = 1) {
return new Promise((resolve, reject) => {
const video = document.createElement('video');
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
video.addEventListener('loadedmetadata', () => {
video.currentTime = time;
});
video.addEventListener('seeked', () => {
canvas.width = video.videoWidth;
canvas.height = video.videoHeight;
ctx.drawImage(video, 0, 0);
canvas.toBlob(resolve, 'image/jpeg', 0.8);
});
video.addEventListener('error', reject);
video.src = URL.createObjectURL(videoFile);
});
}<!-- 不预加载,节省带宽 -->
<video preload="none" controls>
<source src="video.mp4" type="video/mp4">
</video>
<!-- 仅预加载元数据 -->
<video preload="metadata" controls>
<source src="video.mp4" type="video/mp4">
</video>
<!-- 完全预加载(默认) -->
<video preload="auto" controls>
<source src="video.mp4" type="video/mp4">
</video>// 视频懒加载
const videoObserver = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const video = entry.target;
const source = video.querySelector('source');
if (source.dataset.src) {
source.src = source.dataset.src;
video.load();
videoObserver.unobserve(video);
}
}
});
});
// 监听所有视频元素
document.querySelectorAll('video').forEach(video => {
videoObserver.observe(video);
});// 检查视频格式支持
function checkVideoFormat() {
const video = document.createElement('video');
const formats = {
mp4: 'video/mp4; codecs="avc1.42E01E"',
webm: 'video/webm; codecs="vp8"',
ogg: 'video/ogg; codecs="theora"'
};
const supported = {};
for (const [format, codec] of Object.entries(formats)) {
supported[format] = video.canPlayType(codec) !== '';
}
return supported;
}
// 根据支持情况选择格式
function selectBestFormat(formats) {
const supported = checkVideoFormat();
if (supported.webm) return formats.webm;
if (supported.mp4) return formats.mp4;
if (supported.ogg) return formats.ogg;
return formats.mp4; // 默认
}// 检测video元素支持
function supportsVideo() {
return !!document.createElement('video').canPlayType;
}
// 检测特定格式支持
function supportsVideoFormat(format) {
const video = document.createElement('video');
return video.canPlayType(format) !== '';
}
// 使用示例
if (supportsVideo()) {
// 使用HTML5 video
console.log('支持HTML5视频');
} else {
// 降级处理
console.log('不支持HTML5视频,使用替代方案');
}<!-- 移动端友好的视频设置 -->
<video
controls
playsinline
webkit-playsinline
x5-playsinline
x5-video-player-type="h5"
x5-video-orientation="portraint"
>
<source src="video.mp4" type="video/mp4">
</video>// 自适应播放质量
function adaptiveQuality() {
const connection = navigator.connection || navigator.mozConnection || navigator.webkitConnection;
if (connection) {
const effectiveType = connection.effectiveType;
switch(effectiveType) {
case 'slow-2g':
case '2g':
return 'low';
case '3g':
return 'medium';
case '4g':
return 'high';
default:
return 'auto';
}
}
return 'auto';
}
// 根据网络状况调整视频质量
const quality = adaptiveQuality();
console.log('推荐视频质量:', quality);<!-- 提供完整的无障碍支持 -->
<video controls aria-label="教学视频:HTML5基础">
<source src="video.mp4" type="video/mp4">
<track kind="captions" src="captions.vtt" srclang="zh" label="中文字幕" default>
<track kind="descriptions" src="descriptions.vtt" srclang="zh" label="音频描述">
<p>您的浏览器不支持视频播放。
<a href="video.mp4">下载视频文件</a>
</p>
</video>// 内容安全策略
function secureVideoPlayer() {
const video = document.getElementById('myVideo');
// 防止自动播放滥用
if (video.autoplay) {
video.muted = true;
}
// 限制音量
video.addEventListener('volumechange', () => {
if (video.volume > 0.8) {
video.volume = 0.8;
}
});
// 防止长时间播放
video.addEventListener('timeupdate', () => {
if (video.currentTime > 3600) { // 1小时
video.pause();
alert('播放时间过长,已自动暂停');
}
});
}A: 移动设备为了节省流量和电量,通常禁止视频自动播放。需要用户手动触发播放。
A: MP4兼容性最好,WebM文件更小,建议提供多种格式。考虑目标用户的设备和网络状况。
A: 可以使用预加载策略、视频压缩、CDN加速,或者实现自适应码率播放。
A: 可以通过CSS伪元素选择器 ::cue 来自定义WebVTT字幕的样式。
下一节预览:第4章第3节 - 多媒体优化 - 学习多媒体性能优化技术