一、为什么要做这个工具?
不知道你有没有遇到过这种情况:刷抖音/快手看到一个有意思的视频,想保存下来分享给朋友,结果点分享后要么是"复制链接",要么保存的视频带个大大的水印,还有平台 logo,体验特别差。
网上搜了一圈,要么是收费的,要么就是各种弹窗广告,用起来闹心。作为一个程序员,这能忍?自己撸一个吧!
核心痛点总结:
- 平台自带保存功能有水印
- 第三方工具要么收费要么广告多
- 用户体验差,操作繁琐
二、核心功能
说干就干,这个工具支持以下平台:
| 平台 | 支持情况 | 备注 |
|---|---|---|
| 抖音 | ✅ 视频+图文 | 支持无水印视频和图文下载 |
| 快手 | ✅ 视频 | 支持无水印视频下载 |
| 小红书 | ✅ 视频+图文 | 支持笔记和视频下载 |
| B站 | ✅ 视频 | 支持B站视频下载 |
| 微博 | ✅ 视频 | 支持微博视频下载 |
| TikTok | ✅ 视频 | 支持国际版抖音 |
| YouTube | ✅ 视频 | 支持YouTube视频下载 |
| ✅ 视频 | 支持Facebook视频下载 | |
| 皮皮虾 | ✅ 视频 | 支持皮皮虾视频下载 |
主要特性:
- 🚀 一键解析:粘贴链接即可获取无水印视频
- 📋 智能复制:自动复制下载链接到剪贴板
- 🎬 在线预览:支持视频在线播放预览
- 🔧 多平台兼容:支持Windows/Linux部署
- ⚡ 快速响应:解析速度快,体验流畅
三、踩坑实录:那些让我头大的问题
坑1:分享文案里的 URL 被各种符号包裹
用户复制的分享文案长这样:
5.38 复制打开抖音,看看【卡西爸啊!的作品】... `https://v.douyin.com/xxxx/` :3pm m@D.uS
你没看错,链接前后有反引号!一开始我的正则直接提取,结果 URL 后面带个反斜杠,请求直接 404。
解决方案 :加了个 sanitize_url 函数,循环清理 URL 首尾的特殊字符:
python
def sanitize_url(self, url):
if not url:
return None
url = url.strip()
# 清理首尾的反引号、引号、括号、标点符号等
url = re.sub(r'^[`\'"<\(\[\{(【\\\\]+|[`\'">\)\]\})】,,。!!??;;::\\\\]+$', '', url)
# 循环清理,防止多层包裹
while True:
clean_url = re.sub(r'[`\'"<>)】,,。!!??;;::\\\\]+$', '', url)
if clean_url == url:
break
url = clean_url
return url
坑2:HTTP 环境下复制功能失效
部署到生产环境后发现,点击"复制链接"按钮没反应。查了下控制台,原来是 navigator.clipboard 只在 HTTPS 环境下才能用,HTTP 环境直接拒绝访问。
解决方案 :加个降级方案,用传统的 execCommand:
javascript
function fallbackCopyText(text) {
const textarea = document.createElement('textarea');
textarea.value = text;
textarea.style.position = 'fixed';
textarea.style.opacity = '0';
textarea.style.left = '-9999px';
document.body.appendChild(textarea);
textarea.select();
const successful = document.execCommand('copy');
document.body.removeChild(textarea);
return successful;
}
// 优先用 clipboard API,失败了再用 execCommand
if (navigator.clipboard && window.isSecureContext) {
navigator.clipboard.writeText(text).then(...).catch(() => {
fallbackCopyText(text);
});
} else {
fallbackCopyText(text);
}
坑3:视频播放不了,浏览器控制台报混合内容错误
这是最头疼的一个问题。日志显示解析成功,视频链接也拿到了,但页面上视频就是加载不出来。控制台报错:
The file at 'blob: http://xxx/...' was loaded over an insecure connection.
原因是抖音的视频链接有 CORS 限制,而且在 HTTP 页面加载某些外部资源会被浏览器的混合内容策略拦截。
解决方案:加了个视频代理接口,服务器端先下载视频,再流式传输给前端:
python
@app.route('/api/video-proxy', methods=['GET'])
def video_proxy():
url = request.args.get('url', '')
if not url:
return jsonify({'error': '缺少url参数'}), 400
decoded_url = urllib.parse.unquote(url)
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)...',
'Referer': 'https://www.douyin.com/',
}
# 支持 Range 请求,让视频可以拖动进度条
range_header = request.headers.get('Range')
if range_header:
headers['Range'] = range_header
# 流式传输,边下边播
req = requests.get(decoded_url, headers=headers, stream=True, timeout=60)
def generate():
for chunk in req.iter_content(chunk_size=8192):
if chunk:
yield chunk
return Response(
stream_with_context(generate()),
status=206 if req.status_code == 206 else 200,
headers={
'Content-Type': req.headers.get('Content-Type', 'video/mp4'),
'Content-Range': req.headers.get('Content-Range'),
'Content-Length': req.headers.get('Content-Length'),
'Accept-Ranges': req.headers.get('Accept-Ranges'),
}
)
四、项目结构
短视频去水印/
├── app.py # Flask Web 应用(主程序)
├── server.py # 生产环境入口(Waitress服务器)
├── downloader.py # 统一下载器入口
├── logger.py # 日志模块(记录解析日志)
├── config.json # 配置文件(端口、线程数等)
├── parsers/ # 各平台解析器
│ ├── base.py # 解析器基类(抽象接口)
│ ├── factory.py # 解析器工厂(根据URL选择解析器)
│ ├── douyin.py # 抖音解析器
│ ├── kuaishou.py # 快手解析器
│ ├── xiaohongshu.py # 小红书解析器
│ ├── bilibili.py # B站解析器
│ ├── weibo.py # 微博解析器
│ ├── tiktok.py # TikTok解析器
│ ├── youtube.py # YouTube解析器
│ ├── facebook.py # Facebook解析器
│ └── pipixia.py # 皮皮虾解析器
├── utils/ # 工具函数
│ ├── url_utils.py # URL处理工具
│ ├── file_utils.py # 文件处理工具
│ └── network_utils.py # 网络请求工具
├── static/ # 静态资源
│ ├── css/ # 样式文件
│ ├── js/ # JavaScript文件
│ └── images/ # 图片资源
├── templates/ # HTML模板
│ └── index.html # 主页面模板
├── 启动服务器.bat # 一键启动脚本(Windows)
├── 安装为Windows服务.bat # 生产环境部署脚本
└── requirements.txt # Python依赖清单
架构说明:
- MVC模式:采用Flask框架,前后端分离设计
- 插件化解析器:每个平台独立解析器,易于扩展
- 配置驱动:通过config.json灵活配置服务器参数
- 日志记录:完善的日志系统,便于问题排查
五、快速上手
环境要求
- Python 3.7+
- pip 包管理工具
- Windows/Linux/macOS 系统
本地运行
bash
# 1. 克隆项目(如果有Git)
git clone https://github.com/yourusername/video-watermark-remover.git
cd video-watermark-remover
# 2. 安装依赖
pip install -r requirements.txt
# 3. 启动服务
python server.py
# 或者直接运行Flask应用
python app.py
启动成功后,浏览器打开 http://127.0.0.1:9000 就能使用了。
生产环境部署
Windows 服务器部署
推荐使用 NSSM 安装为系统服务:
- 下载 NSSM(Windows服务管理器)
- 将 nssm.exe 放到 System32 目录或项目目录
- 右键"安装为Windows服务.bat",以管理员身份运行
- 服务会自动配置为开机自启
Linux 服务器部署
bash
# 使用systemd管理服务
sudo cp video-watermark.service /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable video-watermark
sudo systemctl start video-watermark
端口配置
默认端口是 9000,可以通过三种方式修改:
方式一:配置文件(推荐)
json
{
"server": {
"host": "0.0.0.0",
"port": 8080,
"threads": 8,
"debug": false,
"ssl": false
}
}
方式二:环境变量
bash
# Windows
set PORT=8080
set HOST=0.0.0.0
python server.py
# Linux/macOS
export PORT=8080
export HOST=0.0.0.0
python server.py
方式三:命令行参数
bash
python server.py --port 8080 --host 127.0.0.1 --threads 4
常见问题
- 端口被占用:修改config.json中的端口号
- 依赖安装失败 :尝试使用国内镜像源
pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple - 服务启动失败:检查Python版本和依赖是否完整安装
六、效果展示
界面长这样,简洁实用:
传送门,点击一键直达:
七、一些感悟与总结
做这个工具的过程中,最深的体会是:看似简单的功能,生产环境部署时到处都是坑。
技术收获
- 正则表达式优化:用户输入千奇百怪,需要更健壮的URL提取逻辑
- 浏览器兼容性:不同浏览器、不同环境(HTTP/HTTPS)下的API差异
- 安全策略应对:CORS、混合内容策略、跨域限制的解决方案
- 性能优化:视频流式传输、Range请求支持、缓存策略
经验教训
- 本地测试一切正常 ≠ 生产环境也能正常运行
- 用户输入永远比你想的更"有创意"
- 浏览器的安全策略越来越严格,需要提前规划
- 日志系统是排查线上问题的关键
未来规划
- 功能扩展:支持更多短视频平台
- 性能优化:增加缓存机制,减少重复解析
- 用户体验:开发浏览器插件,一键解析
- 移动端适配:开发移动端Web应用
不过当你把这些坑一个个填完,看到用户能顺利使用的时候,那种成就感还是挺棒的。
项目地址
在线体验 :http://qushuiyin.51softwarebox.com/
免责声明
本工具仅供个人学习交流使用,请勿用于商业用途。请尊重创作者的知识产权,下载的内容请勿二次上传传播。使用本工具产生的任何后果由使用者自行承担。
交流与贡献
- 有问题或建议?欢迎在评论区留言
- 需要帮助?可以在评论区留言或私信联系
如果你觉得这篇文章对你有帮助,欢迎点赞、收藏、关注!有问题评论区交流~