2024最新YT-DLP使用demo网页端渲染

2024最新YT-DLP使用demo网页端渲染

前提摘要

2024最新python使用yt-dlp

1.使用python的fastapi库和jinjia2库进行前端渲染

需要下载下面对应的python第三方库

pip install fastapi uvicorn python-multipart jinja2 yt-dlp

java 复制代码
功能如下
使用YT-DLP,缓存文件到本地,预览文件信息


2.代码实现

1)目录结构

2)代码

style.css

javascript 复制代码
body {
    font-family: Arial, sans-serif;
    margin: 0;
    padding: 20px;
    background-color: #f0f0f0;
}

.container {
    max-width: 800px;
    margin: 0 auto;
    background-color: white;
    padding: 20px;
    border-radius: 8px;
    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}

/* 添加 logo 相关样式 */
.logo {
    display: flex;
    justify-content: center;
    gap: 8px;
    margin-bottom: 20px;
}

.youtube-icon, .download-icon {
    width: 32px;  /* 调整图标大小 */
    height: 32px; /* 调整图标大小 */
}

.header {
    text-align: center;
    margin-bottom: 30px;
}

h1 {
    font-size: 24px;
    margin: 10px 0;
}

.subtitle {
    color: #666;
    margin-bottom: 20px;
}

form {
    margin: 20px 0;
}

.input-group {
    display: flex;
    gap: 10px;
}

input[type="text"] {
    flex: 1;
    padding: 10px;
    border: 1px solid #ddd;
    border-radius: 4px;
}

button {
    background-color: #007bff;
    color: white;
    padding: 10px 20px;
    border: none;
    border-radius: 4px;
    cursor: pointer;
}

button:hover {
    background-color: #0056b3;
}

.disclaimer {
    text-align: center;
    color: #666;
    font-size: 14px;
    margin: 20px 0;
}

.info-icon {
    color: #007bff;
    cursor: help;
}

.footer {
    text-align: center;
    margin-top: 30px;
    color: #666;
    font-size: 14px;
}

index.html

javascript 复制代码
<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>YouTube 视频下载器</title>
    <link rel="stylesheet" href="{{ url_for('static', path='style.css') }}">
</head>
<body>
    <div class="container">
        <div class="header">
            <div class="logo">
                <svg class="youtube-icon" viewBox="0 0 24 24">
                    <path fill="#FF0000" d="M23.498 6.186a3.016 3.016 0 0 0-2.122-2.136C19.505 3.545 12 3.545 12 3.545s-7.505 0-9.377.505A3.017 3.017 0 0 0 .502 6.186C0 8.07 0 12 0 12s0 3.93.502 5.814a3.016 3.016 0 0 0 2.122 2.136c1.871.505 9.376.505 9.376.505s7.505 0 9.377-.505a3.015 3.015 0 0 0 2.122-2.136C24 15.93 24 12 24 12s0-3.93-.502-5.814zM9.545 15.568V8.432L15.818 12l-6.273 3.568z"/>
                </svg>
                <svg class="download-icon" viewBox="0 0 24 24">
                    <path fill="#4285f4" d="M19 9h-4V3H9v6H5l7 7 7-7zM5 18v2h14v-2H5z"/>
                </svg>
            </div>
            <h1>YT-DLP-DEMO</h1>
            <p class="subtitle">YTDownload</p>
        </div>

        <form action="/download" method="POST">
            <div class="input-group">
                <input type="text" 
                       name="url" 
                       placeholder="https://www.youtube.com/watch?v=..." 
                       required>
                <button type="submit">下载</button>
            </div>
        </form>

        <div class="footer">
            <p>由 FastAPI 和 yt-dlp 提供技术支持</p>
        </div>
    </div>
</body>
</html> 

result.html

javascript 复制代码
<!DOCTYPE html>
<html>
<head>
    <title>Download Result</title>
    <link rel="stylesheet" href="{{ url_for('static', path='style.css') }}">
</head>
<body>
    <div class="container">
        {% if success %}
            <div class="result-info">
                <div class="video-header">
                    <div class="video-details">
                        <h2>{{ video_info.title }}</h2>
                        <div class="meta-info">
                            <p><strong>作者:</strong> {{ video_info.author }}</p>
                            <p><strong>时长:</strong> {{ video_info.length }}</p>
                            <p><strong>观看次数:</strong> {{ '{:,}'.format(video_info.views) }}</p>
                        </div>
                    </div>
                </div>
                
                <div class="download-sections">
                    <div class="preview-section">
                        <h3>视频预览</h3>
                        <div class="preview-container">
                            <video controls>
                                <source src="{{ video_path }}" type="video/mp4">
                                您的浏览器不支持视频标签。
                            </video>
                        </div>
                        <a href="{{ video_path }}" class="download-button" download>
                            <span class="icon">⭳</span> 下载视频
                        </a>
                    </div>
                    
                    <div class="preview-section">
                        <h3>音频预览</h3>
                        <div class="preview-container">
                            <audio controls>
                                <source src="{{ audio_path }}" type="audio/mp4">
                                您的浏览器不支持音频标签。
                            </audio>
                        </div>
                        <a href="{{ audio_path }}" class="download-button" download>
                            <span class="icon">⭳</span> 下载音频
                        </a>
                    </div>
                </div>
            </div>
        {% else %}
            <div class="error-container">
                <h2>下载失败</h2>
                <p class="error-message">{{ error }}</p>
            </div>
        {% endif %}
        
        <a href="/" class="back-button">返回首页</a>
    </div>
</body>
</html> 

main.py

javascript 复制代码
from fastapi import FastAPI, Request, Form
from fastapi.templating import Jinja2Templates
from fastapi.staticfiles import StaticFiles
from fastapi.responses import FileResponse
import yt_dlp
from pathlib import Path
import os

app = FastAPI()

# 配置静态文件和模板
app.mount("/static", StaticFiles(directory="static"), name="static")
templates = Jinja2Templates(directory="templates")

# 配置下载目录
VIDEO_DIR = Path("downloads/video")
AUDIO_DIR = Path("downloads/audio")
VIDEO_DIR.mkdir(parents=True, exist_ok=True)
AUDIO_DIR.mkdir(parents=True, exist_ok=True)

def download_youtube_video(url):
    try:
        # yt-dlp 基础配置
        common_opts = {
            'cookiefile': r'www.youtube.com_cookies.txt',
            'quiet': False,
            'no_warnings': False,
            'verbose': True,
            'proxy': 'http://127.0.0.1:10809',
            'socket_timeout': 30,
            'retries': 3,
            'nocheckcertificate': True,
            'prefer_insecure': True
        }

        # 视频下载选项
        video_opts = {
            **common_opts,
            'format': 'best[ext=mp4][height<=720]/best[height<=720]/best',
            'outtmpl': str(VIDEO_DIR / '%(title)s.%(ext)s'),
        }

        # 音频下载选项
        audio_opts = {
            **common_opts,
            'format': 'bestaudio[ext=m4a]/bestaudio',
            'outtmpl': str(AUDIO_DIR / '%(title)s.%(ext)s'),
        }

        # 获取视频信息
        with yt_dlp.YoutubeDL(common_opts) as ydl:
            info = ydl.extract_info(url, download=False)
            title = info['title']
            duration = info['duration']
            thumbnail = info['thumbnail']
            author = info.get('uploader', 'Unknown')
            views = info.get('view_count', 0)

        # 下载视频
        with yt_dlp.YoutubeDL(video_opts) as ydl:
            ydl.download([url])

        # 下载音频
        with yt_dlp.YoutubeDL(audio_opts) as ydl:
            ydl.download([url])

        # 获取下载后的文件路径
        video_file = next(VIDEO_DIR.glob(f"{title}.*"))
        audio_file = next(AUDIO_DIR.glob(f"{title}.*"))

        return {
            "status": "success",
            "title": title,
            "author": author,
            "duration": f"{duration // 60}:{duration % 60:02d}",
            "views": views,
            "thumbnail": thumbnail,
            "video_path": str(video_file.name),
            "audio_path": str(audio_file.name)
        }
    except Exception as e:
        return {"status": "error", "message": str(e)}

@app.get("/")
async def home(request: Request):
    return templates.TemplateResponse("index.html", {"request": request})

@app.post("/download")
async def download_video_route(request: Request, url: str = Form(...)):
    try:
        result = download_youtube_video(url)
        
        if result["status"] == "success":
            video_info = {
                "title": result["title"],
                "author": result["author"],
                "length": result["duration"],
                "views": result["views"],
                "thumbnail": result["thumbnail"]
            }
            
            return templates.TemplateResponse("result.html", {
                "request": request,
                "video_info": video_info,
                "video_path": f"/downloads/video/{result['video_path']}",
                "audio_path": f"/downloads/audio/{result['audio_path']}",
                "success": True
            })
        else:
            raise Exception(result["message"])
            
    except Exception as e:
        return templates.TemplateResponse("result.html", {
            "request": request,
            "error": str(e),
            "success": False
        })

# 配置下载目录的静态文件服务
app.mount("/downloads", StaticFiles(directory="downloads"), name="downloads") 

run.py

javascript 复制代码
import uvicorn
import os

def check_directories():
    """确保必要的目录存在"""
    directories = [
        'static',
        'templates',
        'downloads',
        'downloads/video',
        'downloads/audio'
    ]
    for directory in directories:
        if not os.path.exists(directory):
            os.makedirs(directory)
            print(f"Created directory: {directory}")

if __name__ == "__main__":
    # 检查并创建必要的目录
    check_directories()
    
    # 配置并启动服务器
    uvicorn.run(
        "main:app", 
        host="127.0.0.1", 
        port=8000, 
        reload=True,
        reload_dirs=["templates", "static"],
        log_level="info"
    ) 

3)运行测试

命令端运行

pip install fastapi uvicorn python-multipart jinja2 yt-dlp

python run.py

3.项目下载地址

https://github.com/unkownc/python_demo/tree/main

相关推荐
思则变2 小时前
[Pytest] [Part 2]增加 log功能
开发语言·python·pytest
漫谈网络2 小时前
WebSocket 在前后端的完整使用流程
javascript·python·websocket
try2find4 小时前
安装llama-cpp-python踩坑记
开发语言·python·llama
博观而约取5 小时前
Django ORM 1. 创建模型(Model)
数据库·python·django
精灵vector6 小时前
构建专家级SQL Agent交互
python·aigc·ai编程
Zonda要好好学习6 小时前
Python入门Day2
开发语言·python
Vertira6 小时前
pdf 合并 python实现(已解决)
前端·python·pdf
太凉6 小时前
Python之 sorted() 函数的基本语法
python
项目題供诗7 小时前
黑马python(二十四)
开发语言·python
晓13137 小时前
OpenCV篇——项目(二)OCR文档扫描
人工智能·python·opencv·pycharm·ocr