根据视频链接下载视频html
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>视频下载工具</title>
<meta name="referrer" content="no-referrer">
<style>
body {
font-family: Arial, sans-serif;
max-width: 800px;
margin: 0 auto;
padding: 20px;
box-sizing: border-box;
}
.container {
text-align: center;
padding: 40px 20px;
border-radius: 8px;
background-color: #f5f5f5;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}
h1 {
color: #333;
margin-bottom: 30px;
}
.input-group {
display: flex;
margin-bottom: 20px;
}
.link {
flex: 1;
padding: 10px;
font-size: 16px;
border: 1px solid #ddd;
border-radius: 4px 0 0 4px;
outline: none;
}
.download-btn {
padding: 10px 20px;
font-size: 16px;
background-color: #4CAF50;
color: white;
border: none;
border-radius: 0 4px 4px 0;
cursor: pointer;
outline: none;
}
.download-btn:hover {
background-color: #45a049;
}
.download-btn .loading {
display: none;
}
.progress-container {
width: 100%;
height: 20px;
background-color: #f1f1f1;
border-radius: 10px;
margin-bottom: 10px;
display: none;
}
.progress-bar {
height: 100%;
background-color: #4CAF50;
border-radius: 10px;
width: 0%;
transition: width 0.3s ease;
}
.status-message {
color: #333;
margin-top: 10px;
}
.divhidden {
display: none !important;
}
/* 预览视频样式 */
.preview-section {
margin-top: 30px;
text-align: left;
}
.video-preview {
width: 100%;
border-radius: 4px;
margin-top: 10px;
}
.preview-controls {
margin-top: 10px;
}
.preview-btn {
padding: 8px 16px;
margin-right: 10px;
background-color: #2196F3;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
}
.preview-btn:hover {
background-color: #0b7dda;
}
</style>
<!-- Code injected by Five-server -->
<script async data-id="five-server" data-file="c:\Users\22560\Desktop\新建文件夹\1.html" type="application/javascript" src="/fiveserver.js"></script>
</head>
<body>
<div class="container">
<h1>视频下载工具</h1>
<!-- 视频链接输入区域 -->
<div class="input-group">
<input type="text" class="link" placeholder="请输入视频链接..." />
<button type="button" class="download-btn Startparsing">
<span>下载视频</span>
<span class="loading">下载中...</span>
</button>
</div>
<!-- 下载进度条 -->
<div class="progress-container">
<div class="progress-bar"></div>
</div>
<!-- 下载状态信息 -->
<div class="status-message"></div>
<!-- 视频预览区域 -->
<div class="preview-section divhidden">
<h3>视频预览</h3>
<video class="video-preview" controls></video>
<div class="preview-controls">
<button type="button" class="preview-btn downVideo">重新下载</button>
<button type="button" class="preview-btn copyText">复制视频链接</button>
</div>
</div>
</div>
<script>
// 页面加载完成后执行
document.addEventListener('DOMContentLoaded', function() {
// 初始化配置显示
configShow();
// 监听页面可见性变化
document.addEventListener("visibilitychange", function() {
if (document.visibilityState === "visible") {
configShow();
}
});
});
// 配置显示函数
function configShow() {
// 这里可以添加一些配置显示逻辑
}
// 下载按钮点击事件
document.querySelector('.Startparsing').addEventListener('click', function() {
let link = document.querySelector('.link').value;
if (!link) {
alert('请输入要下载的视频链接');
return;
}
this.querySelector('.loading').classList.remove('divhidden');
document.querySelector('.status-message').textContent = '正在准备下载...';
// 尝试获取文件扩展名
let videoExtension = getFileExtension(link) || 'mp4';
// 显示预览区域
document.querySelector('.preview-section').classList.remove('divhidden');
document.querySelector('.video-preview').src = link;
// 开始下载
downloadFileWithProgress(link, `视频.${videoExtension}`).then(() => {
this.querySelector('.loading').classList.add('divhidden');
document.querySelector('.status-message').textContent = '下载完成';
}).catch(error => {
this.querySelector('.loading').classList.add('divhidden');
document.querySelector('.status-message').textContent = `下载失败: ${error.message}`;
});
});
// 重新下载按钮点击事件
document.querySelector('.downVideo').addEventListener('click', function() {
let videoElement = document.querySelector('.video-preview');
let link = videoElement.src;
if (!link) {
alert('没有可下载的视频链接');
return;
}
let videoExtension = getFileExtension(link) || 'mp4';
document.querySelector('.Startparsing').querySelector('.loading').classList.remove('divhidden');
document.querySelector('.status-message').textContent = '正在准备下载...';
downloadFileWithProgress(link, `视频.${videoExtension}`).then(() => {
document.querySelector('.Startparsing').querySelector('.loading').classList.add('divhidden');
document.querySelector('.status-message').textContent = '下载完成';
}).catch(error => {
document.querySelector('.Startparsing').querySelector('.loading').classList.add('divhidden');
document.querySelector('.status-message').textContent = `下载失败: ${error.message}`;
});
});
// 复制链接按钮点击事件
document.querySelector('.copyText').addEventListener('click', function() {
let videoElement = document.querySelector('.video-preview');
let link = videoElement.src;
if (!link) {
alert('没有可复制的链接');
return;
}
copyText(link);
});
// 获取文件扩展名
function getFileExtension(url) {
// 查找URL中最后一个'.'的位置
const lastDotIndex = url.lastIndexOf('.');
// 检查是否找到了'.'并且它不是在URL的开头
if (lastDotIndex !== -1 && lastDotIndex !== url.length - 1) {
// 从最后一个'.'开始截取字符串直到URL的末尾或查询参数开始
let extension = url.substring(lastDotIndex + 1);
const queryIndex = extension.indexOf('?');
if (queryIndex !== -1) {
extension = extension.substring(0, queryIndex);
}
// 限制扩展名长度,防止无效的扩展名
if (extension.length > 10) {
return 'mp4';
}
return extension;
}
// 如果没有找到有效的文件扩展名,返回null
return null;
}
// 复制文本到剪贴板
function copyText(text) {
if (navigator.clipboard && window.isSecureContext) {
navigator.clipboard.writeText(text).then(() => {
alert('链接已复制到剪贴板');
}).catch(err => {
alert('复制失败,请手动复制');
});
} else {
// 兼容旧浏览器
const textArea = document.createElement('textarea');
textArea.value = text;
textArea.style.position = 'fixed';
textArea.style.left = '-999999px';
textArea.style.top = '-999999px';
document.body.appendChild(textArea);
textArea.focus();
textArea.select();
try {
document.execCommand('copy');
alert('链接已复制到剪贴板');
} catch (err) {
alert('复制失败,请手动复制');
}
document.body.removeChild(textArea);
}
}
// 带进度的文件下载函数
async function downloadFileWithProgress(url, filename) {
return new Promise((resolve, reject) => {
// 显示进度条
const progressContainer = document.querySelector('.progress-container');
const progressBar = document.querySelector('.progress-bar');
const statusMessage = document.querySelector('.status-message');
progressContainer.classList.remove('divhidden');
progressBar.style.width = '0%';
statusMessage.textContent = '开始下载...';
// 使用fetch API进行下载
fetch(url, {
method: 'GET',
headers: {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36',
'Accept': 'video/mp4,video/webm,video/*;q=0.9,application/ogg;q=0.7,audio/*;q=0.6,*/*;q=0.5'
}
}).then(response => {
if (!response.ok) {
throw new Error(`HTTP错误: 状态码 ${response.status}`);
}
const contentLength = response.headers.get('content-length');
let downloadedLength = 0;
const reader = response.body.getReader();
const stream = new ReadableStream({
start(controller) {
function read() {
reader.read().then(({ done, value }) => {
if (done) {
controller.close();
return;
}
downloadedLength += value.length;
// 更新进度条
if (contentLength) {
const progress = (downloadedLength / parseInt(contentLength)) * 100;
progressBar.style.width = `${progress}%`;
statusMessage.textContent = `正在下载: ${Math.round(progress)}%`;
} else {
statusMessage.textContent = `正在下载: ${formatFileSize(downloadedLength)}`;
}
controller.enqueue(value);
read();
}).catch(error => {
reject(error);
});
}
read();
}
});
// 创建新的响应对象
const newResponse = new Response(stream);
return newResponse.blob().then(blob => {
// 创建下载链接
const url = window.URL.createObjectURL(blob);
const a = document.createElement('a');
a.style.display = 'none';
a.href = url;
a.download = filename;
document.body.appendChild(a);
a.click();
// 清理
setTimeout(() => {
window.URL.revokeObjectURL(url);
document.body.removeChild(a);
progressContainer.classList.add('divhidden');
resolve();
}, 100);
});
}).catch(error => {
progressContainer.classList.add('divhidden');
statusMessage.textContent = `下载失败: ${error.message}`;
reject(error);
});
});
}
// 格式化文件大小显示
function formatFileSize(bytes) {
if (bytes === 0) return '0 Bytes';
const k = 1024;
const sizes = ['Bytes', 'KB', 'MB', 'GB'];
const i = Math.floor(Math.log(bytes) / Math.log(k));
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
}
</script>
</body>
</html>