12.メモ

Python

Views.py 20250427

from django.shortcuts import render, redirect, get_object_or_404
from django.views.decorators.http import require_POST
from .forms import AppForm
from .models import App
import yt_dlp
from pathlib import Path
import os
from django.http import StreamingHttpResponse
import time
import threading

# 進捗バーを0.5秒おきに更新
progress = 0
def progress_stream(request):
    def event_stream():
        global progress
        while progress < 100:
            yield f"data: {progress}\n\n"
            time.sleep(0.5)
        yield f"data: 100\n\n"
    return StreamingHttpResponse(event_stream(), content_type="text/event-stream")

# 進捗バーを0%にしてダウンロード開始
def download_video(url, format_choice):
    global progress
    progress = 0

    download_path = str(Path.home() / "Downloads")

    def progress_hook(d):
        global progress
        if d['status'] == 'downloading':
            total = d.get('total_bytes') or d.get('total_bytes_estimate')
            downloaded = d.get('downloaded_bytes', 0)
            if total:
                percent = downloaded / total * 100
                progress = int(percent)
        elif d['status'] == 'finished':
            progress = 100

    option = {
        'outtmpl': os.path.join(download_path, '%(title)s.%(ext)s'),
        'progress_hooks': [progress_hook],
    }

    if format_choice == 'mp4':
        option['format'] = 'bestvideo+bestaudio/best'
        option['merge_output_format'] = 'mp4'
    elif format_choice == 'mp3':
        option['format'] = 'bestaudio/best'
        option['postprocessors'] = [{
            'key': 'FFmpegExtractAudio',
            'preferredcodec': 'mp3',
            'preferredquality': '192',
        }]
    elif format_choice == 'thumbnail':
        option['writethumbnail'] = 'embed=thumbnail'


    with yt_dlp.YoutubeDL(option) as yd:
        yd.download([url])

def index(request):
    global progress
    if request.method == "POST":
        form = AppForm(request.POST)
        if form.is_valid():
            saved = form.save()
            url = saved.url
            format_choice = form.cleaned_data['format']
            # 新しいスレッドでダウンロードを開始
            threading.Thread(target=download_video, args=(url, format_choice), daemon=True).start()
            return render(request, 'app/index.html', {'form': AppForm()})
    else:
        form = AppForm()
    return render(request, 'app/index.html', {'form': form})

def new(request):
    return render(request, 'app/new.html')

BACK