<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>视频加水印工具</title>
<style>
body {
font-family: Arial, sans-serif;
max-width: 800px;
margin: 0 auto;
padding: 20px;
}
.config-area {
margin: 20px 0;
padding: 15px;
border: 1px solid #ddd;
border-radius: 5px;
}
.config-area div {
margin: 10px 0;
}
.config-area label {
display: inline-block;
width: 180px;
}
.config-area input {
padding: 5px;
width: 80px;
}
.upload-area {
margin-bottom: 20px;
padding: 20px;
border: 2px dashed #ccc;
text-align: center;
}
button {
padding: 10px 20px;
background-color: #4CAF50;
color: white;
border: none;
cursor: pointer;
margin: 10px 0;
}
button:disabled {
background-color: #cccccc;
}
#downloadLink {
display: none;
margin-top: 20px;
}
</style>
</head>
<body>
<h1>视频加水印工具</h1>
<div class="upload-area">
<h3>上传视频文件</h3>
<input type="file" id="videoInput" accept="video/*">
</div>
<div class="upload-area">
<h3>上传水印图片</h3>
<input type="file" id="watermarkInput" accept="image/*">
</div>
<div class="config-area">
<h3>水印配置</h3>
<div>
<label>距离左侧(px):</label>
<input type="number" id="offsetLeft" value="20" min="0">
</div>
<div>
<label>距离底部(px):</label>
<input type="number" id="offsetBottom" value="20" min="0">
</div>
<div>
<label>水印高度(px):</label>
<input type="number" id="watermarkHeight" value="50" min="10">
</div>
</div>
<button id="processBtn" disabled>处理视频</button>
<div id="status"></div>
<div id="progress" style="margin: 10px 0; font-size: 16px;"></div>
<a id="downloadLink" download="watermarked_video.mp4">下载处理后的视频</a>
<script>
let videoFile = null;
let watermarkFile = null;
let mediaRecorder = null;
let recordedChunks = [];
const videoInput = document.getElementById('videoInput');
const watermarkInput = document.getElementById('watermarkInput');
const processBtn = document.getElementById('processBtn');
const downloadLink = document.getElementById('downloadLink');
const statusDiv = document.getElementById('status');
videoInput.addEventListener('change', handleVideoUpload);
watermarkInput.addEventListener('change', handleWatermarkUpload);
processBtn.addEventListener('click', processVideo);
function handleVideoUpload(e) {
videoFile = e.target.files[0];
checkReadyState();
}
function handleWatermarkUpload(e) {
watermarkFile = e.target.files[0];
checkReadyState();
}
function checkReadyState() {
if (videoFile && watermarkFile) {
processBtn.disabled = false;
} else {
processBtn.disabled = true;
}
}
function processVideo() {
statusDiv.textContent = '处理中...';
document.getElementById('progress').textContent = '0%';
processBtn.disabled = true;
const video = document.createElement('video');
video.src = URL.createObjectURL(videoFile);
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
const watermarkImg = new Image();
watermarkImg.src = URL.createObjectURL(watermarkFile);
watermarkImg.onload = function() {
video.onloadedmetadata = function() {
canvas.width = video.videoWidth;
canvas.height = video.videoHeight;
const stream = canvas.captureStream();
const mimeType = MediaRecorder.isTypeSupported('video/mp4')
? 'video/mp4; codecs="avc1.42E01E"'
: 'video/webm';
mediaRecorder = new MediaRecorder(stream, {
mimeType: mimeType
});
mediaRecorder.ondataavailable = function(e) {
if (e.data.size > 0) {
recordedChunks.push(e.data);
}
};
mediaRecorder.onstop = function() {
const fileExtension = mimeType.includes('mp4') ? 'mp4' : 'webm';
const blob = new Blob(recordedChunks, {
type: mimeType
});
downloadLink.href = URL.createObjectURL(blob);
downloadLink.download = `watermarked_video.${fileExtension}`;
downloadLink.style.display = 'block';
statusDiv.textContent = `处理完成!格式: ${fileExtension}`;
};
mediaRecorder.start();
video.addEventListener('play', function() {
function drawFrame() {
if (video.paused || video.ended) {
mediaRecorder.stop();
return;
}
const progress = Math.round((video.currentTime / video.duration) * 100);
document.getElementById('progress').textContent = `${progress}%`;
ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
const offsetLeft = parseInt(document.getElementById('offsetLeft').value);
const offsetBottom = parseInt(document.getElementById('offsetBottom').value);
const desiredHeight = parseInt(document.getElementById('watermarkHeight').value);
const scale = desiredHeight / watermarkImg.height;
const watermarkWidth = watermarkImg.width * scale;
const watermarkHeight = desiredHeight;
const xPos = offsetLeft;
const yPos = canvas.height - watermarkHeight - offsetBottom;
ctx.drawImage(
watermarkImg,
xPos, yPos,
watermarkWidth, watermarkHeight
);
requestAnimationFrame(drawFrame);
}
drawFrame();
});
video.play();
};
};
}
</script>
</body>
</html>