bug vix4
This commit is contained in:
@@ -5,6 +5,7 @@ import os
|
|||||||
import logging
|
import logging
|
||||||
import subprocess
|
import subprocess
|
||||||
import shutil
|
import shutil
|
||||||
|
import asyncio
|
||||||
from typing import List
|
from typing import List
|
||||||
|
|
||||||
from config import (
|
from config import (
|
||||||
@@ -28,11 +29,7 @@ def _progress_hook(cancel_event, progress_cb):
|
|||||||
|
|
||||||
def optimize_for_telegram(input_path: str, output_path: str) -> None:
|
def optimize_for_telegram(input_path: str, output_path: str) -> None:
|
||||||
"""
|
"""
|
||||||
Конвертирует видео в Telegram-safe формат:
|
Синхронная функция: конвертирует видео в Telegram-safe mp4
|
||||||
- mp4 + h264 + aac
|
|
||||||
- четные размеры
|
|
||||||
- crf: 23 (или 28 >50MB)
|
|
||||||
- faststart
|
|
||||||
"""
|
"""
|
||||||
file_size_mb = os.path.getsize(input_path) / (1024 * 1024)
|
file_size_mb = os.path.getsize(input_path) / (1024 * 1024)
|
||||||
crf = 28 if file_size_mb > 50 else 23
|
crf = 28 if file_size_mb > 50 else 23
|
||||||
@@ -66,10 +63,9 @@ def download_video(
|
|||||||
cancel_event: threading.Event,
|
cancel_event: threading.Event,
|
||||||
progress_cb,
|
progress_cb,
|
||||||
):
|
):
|
||||||
# 1. Скачиваем в любой формат
|
|
||||||
ydl_opts = {
|
ydl_opts = {
|
||||||
"format": f"best[height<={quality}]/best",
|
"format": f"best[height<={quality}]/best",
|
||||||
"outtmpl": out_path, # ← без .mp4!
|
"outtmpl": out_path,
|
||||||
"cookiefile": cookies if cookies and os.path.exists(cookies) else None,
|
"cookiefile": cookies if cookies and os.path.exists(cookies) else None,
|
||||||
"progress_hooks": [_progress_hook(cancel_event, progress_cb)],
|
"progress_hooks": [_progress_hook(cancel_event, progress_cb)],
|
||||||
"quiet": True,
|
"quiet": True,
|
||||||
@@ -81,7 +77,7 @@ def download_video(
|
|||||||
with yt_dlp.YoutubeDL(ydl_opts) as ydl:
|
with yt_dlp.YoutubeDL(ydl_opts) as ydl:
|
||||||
ydl.download([url])
|
ydl.download([url])
|
||||||
|
|
||||||
# 2. Ищем реальный файл (без расширения, .mp4, .mov, .webm)
|
# Ищем реальный файл
|
||||||
base = out_path.rsplit('.', 1)[0]
|
base = out_path.rsplit('.', 1)[0]
|
||||||
actual_video = None
|
actual_video = None
|
||||||
for ext in ['', '.mp4', '.mov', '.webm', '.mkv']:
|
for ext in ['', '.mp4', '.mov', '.webm', '.mkv']:
|
||||||
@@ -93,11 +89,11 @@ def download_video(
|
|||||||
if not actual_video:
|
if not actual_video:
|
||||||
raise Exception(f"Video file not created for {url}")
|
raise Exception(f"Video file not created for {url}")
|
||||||
|
|
||||||
# 3. Конвертируем в Telegram-safe mp4
|
# Конвертируем в Telegram-safe mp4 (синхронно)
|
||||||
optimized_path = base + "_telegram.mp4"
|
optimized_path = base + "_telegram.mp4"
|
||||||
await asyncio.to_thread(optimize_for_telegram, actual_video, optimized_path)
|
optimize_for_telegram(actual_video, optimized_path) # ← без await!
|
||||||
|
|
||||||
# 4. Удаляем оригинальный файл и ставим конвертированный
|
# Удаляем старый файл и ставим конвертированный
|
||||||
for path in [out_path, actual_video]:
|
for path in [out_path, actual_video]:
|
||||||
if os.path.exists(path): os.remove(path)
|
if os.path.exists(path): os.remove(path)
|
||||||
os.rename(optimized_path, out_path)
|
os.rename(optimized_path, out_path)
|
||||||
@@ -113,7 +109,7 @@ def download_audio(
|
|||||||
):
|
):
|
||||||
ydl_opts = {
|
ydl_opts = {
|
||||||
"format": "bestaudio/best",
|
"format": "bestaudio/best",
|
||||||
"outtmpl": out_path.replace('.mp3', ''), # ← без .mp3!
|
"outtmpl": out_path.replace('.mp3', ''),
|
||||||
"cookiefile": cookies if cookies and os.path.exists(cookies) else None,
|
"cookiefile": cookies if cookies and os.path.exists(cookies) else None,
|
||||||
"progress_hooks": [_progress_hook(cancel_event, progress_cb)],
|
"progress_hooks": [_progress_hook(cancel_event, progress_cb)],
|
||||||
"postprocessors": [{
|
"postprocessors": [{
|
||||||
@@ -130,7 +126,7 @@ def download_audio(
|
|||||||
with yt_dlp.YoutubeDL(ydl_opts) as ydl:
|
with yt_dlp.YoutubeDL(ydl_opts) as ydl:
|
||||||
ydl.download([url])
|
ydl.download([url])
|
||||||
|
|
||||||
# Ищем файл (может быть .m4a, .opus, .weba)
|
# Ищем файл
|
||||||
base = out_path.rsplit('.', 1)[0]
|
base = out_path.rsplit('.', 1)[0]
|
||||||
actual_audio = None
|
actual_audio = None
|
||||||
for ext in ['', '.mp3', '.m4a', '.opus', '.weba']:
|
for ext in ['', '.mp3', '.m4a', '.opus', '.weba']:
|
||||||
@@ -142,18 +138,15 @@ def download_audio(
|
|||||||
if not actual_audio:
|
if not actual_audio:
|
||||||
raise Exception(f"Audio file not created for {url}")
|
raise Exception(f"Audio file not created for {url}")
|
||||||
|
|
||||||
# Конвертируем в mp3 (если нужно)
|
# Конвертируем в mp3
|
||||||
if actual_audio != out_path:
|
if actual_audio != out_path:
|
||||||
optimized = base + "_telegram.mp3"
|
optimized = base + "_telegram.mp3"
|
||||||
subprocess.run([
|
optimize_for_telegram_audio(actual_audio, optimized) # ← отдельная функция
|
||||||
'ffmpeg', '-i', actual_audio, '-c:a', 'aac', '-b:a', '192k',
|
|
||||||
'-loglevel', 'error', '-y', optimized
|
|
||||||
])
|
|
||||||
if os.path.exists(out_path): os.remove(out_path)
|
if os.path.exists(out_path): os.remove(out_path)
|
||||||
os.rename(optimized, out_path)
|
os.rename(optimized, out_path)
|
||||||
|
|
||||||
|
|
||||||
# ---------------- TIKTOK: Video + Audio (автоматически) ------
|
# ---------------- TikTok: Video + Audio (автоматически) ------
|
||||||
def download_tiktok_video_and_audio(
|
def download_tiktok_video_and_audio(
|
||||||
url: str,
|
url: str,
|
||||||
video_path: str,
|
video_path: str,
|
||||||
@@ -162,10 +155,10 @@ def download_tiktok_video_and_audio(
|
|||||||
cancel_event: threading.Event,
|
cancel_event: threading.Event,
|
||||||
progress_cb,
|
progress_cb,
|
||||||
):
|
):
|
||||||
# 1. Скачиваем видео
|
# Скачиваем видео
|
||||||
video_opts = {
|
video_opts = {
|
||||||
"format": f"bestvideo[height<={DEFAULT_TIKTOK_VIDEO_QUALITY}]+bestaudio/best",
|
"format": f"bestvideo[height<={DEFAULT_TIKTOK_VIDEO_QUALITY}]+bestaudio/best",
|
||||||
"outtmpl": video_path, # ← без .mp4!
|
"outtmpl": video_path,
|
||||||
"cookiefile": cookies if cookies and os.path.exists(cookies) else None,
|
"cookiefile": cookies if cookies and os.path.exists(cookies) else None,
|
||||||
"progress_hooks": [_progress_hook(cancel_event, progress_cb)],
|
"progress_hooks": [_progress_hook(cancel_event, progress_cb)],
|
||||||
"quiet": True,
|
"quiet": True,
|
||||||
@@ -177,6 +170,7 @@ def download_tiktok_video_and_audio(
|
|||||||
with yt_dlp.YoutubeDL(video_opts) as ydl:
|
with yt_dlp.YoutubeDL(video_opts) as ydl:
|
||||||
ydl.download([url])
|
ydl.download([url])
|
||||||
|
|
||||||
|
# Ищем видеофайл
|
||||||
base_video = video_path.rsplit('.', 1)[0]
|
base_video = video_path.rsplit('.', 1)[0]
|
||||||
actual_video = None
|
actual_video = None
|
||||||
for ext in ['', '.mp4', '.mov', '.webm']:
|
for ext in ['', '.mp4', '.mov', '.webm']:
|
||||||
@@ -187,14 +181,14 @@ def download_tiktok_video_and_audio(
|
|||||||
if not actual_video:
|
if not actual_video:
|
||||||
raise Exception("TikTok video file not created")
|
raise Exception("TikTok video file not created")
|
||||||
|
|
||||||
# Конвертируем в Telegram-safe
|
# Конвертируем в Telegram-safe mp4
|
||||||
optimized_video = base_video + "_telegram.mp4"
|
optimized_video = base_video + "_telegram.mp4"
|
||||||
await asyncio.to_thread(optimize_for_telegram, actual_video, optimized_video)
|
optimize_for_telegram(actual_video, optimized_video)
|
||||||
for path in [video_path, actual_video]:
|
for path in [video_path, actual_video]:
|
||||||
if os.path.exists(path): os.remove(path)
|
if os.path.exists(path): os.remove(path)
|
||||||
os.rename(optimized_video, video_path)
|
os.rename(optimized_video, video_path)
|
||||||
|
|
||||||
# 2. Аудио
|
# Аудио
|
||||||
audio_opts = {
|
audio_opts = {
|
||||||
"format": "bestaudio/best",
|
"format": "bestaudio/best",
|
||||||
"outtmpl": audio_path.replace('.mp3', ''),
|
"outtmpl": audio_path.replace('.mp3', ''),
|
||||||
@@ -225,15 +219,12 @@ def download_tiktok_video_and_audio(
|
|||||||
|
|
||||||
if actual_audio != audio_path:
|
if actual_audio != audio_path:
|
||||||
optimized_audio = base_audio + "_telegram.mp3"
|
optimized_audio = base_audio + "_telegram.mp3"
|
||||||
subprocess.run([
|
optimize_for_telegram_audio(actual_audio, optimized_audio)
|
||||||
'ffmpeg', '-i', actual_audio, '-c:a', 'aac', '-b:a', '192k',
|
|
||||||
'-loglevel', 'error', '-y', optimized_audio
|
|
||||||
])
|
|
||||||
if os.path.exists(audio_path): os.remove(audio_path)
|
if os.path.exists(audio_path): os.remove(audio_path)
|
||||||
os.rename(optimized_audio, audio_path)
|
os.rename(optimized_audio, audio_path)
|
||||||
|
|
||||||
|
|
||||||
# ---------------- INSTAGRAM: Video (1080p) ------
|
# ---------------- Instagram: Video (1080p) ------
|
||||||
def download_instagram_video(
|
def download_instagram_video(
|
||||||
url: str,
|
url: str,
|
||||||
out_path: str,
|
out_path: str,
|
||||||
@@ -266,12 +257,27 @@ def download_instagram_video(
|
|||||||
raise Exception("Instagram video not created")
|
raise Exception("Instagram video not created")
|
||||||
|
|
||||||
optimized = base + "_telegram.mp4"
|
optimized = base + "_telegram.mp4"
|
||||||
await asyncio.to_thread(optimize_for_telegram, actual, optimized)
|
optimize_for_telegram(actual, optimized)
|
||||||
if os.path.exists(out_path): os.remove(out_path)
|
if os.path.exists(out_path): os.remove(out_path)
|
||||||
os.rename(optimized, out_path)
|
os.rename(optimized, out_path)
|
||||||
|
|
||||||
|
|
||||||
# ---------------- PLAYLIST ------
|
# ---------------- Audio helper (синхронная) ------
|
||||||
|
def optimize_for_telegram_audio(input_path: str, output_path: str) -> None:
|
||||||
|
"""Конвертирует аудио в Telegram-safe mp3"""
|
||||||
|
cmd = [
|
||||||
|
'ffmpeg',
|
||||||
|
'-i', input_path,
|
||||||
|
'-c:a', 'aac',
|
||||||
|
'-b:a', '192k',
|
||||||
|
'-loglevel', 'error',
|
||||||
|
'-y',
|
||||||
|
output_path
|
||||||
|
]
|
||||||
|
subprocess.run(cmd, capture_output=True, text=True, timeout=600)
|
||||||
|
|
||||||
|
|
||||||
|
# ---------------- Playlist ------
|
||||||
def download_playlist_videos(
|
def download_playlist_videos(
|
||||||
playlist_info: dict,
|
playlist_info: dict,
|
||||||
output_dir: str,
|
output_dir: str,
|
||||||
|
|||||||
Reference in New Issue
Block a user