Added and updated repositories 2026-01-10 01:09:56

This commit is contained in:
github-actions[bot]
2026-01-10 01:09:56 +00:00
parent 1c99e02dd0
commit 572fb61011
67 changed files with 5294 additions and 1704 deletions

View File

@@ -24,82 +24,109 @@
# meta developer: @hikka_mods
# scope: Video2GIF
# scope: Video2GIF 0.0.1
# requires: moviepy
# ---------------------------------------------------------------------------------
import asyncio
import logging
import os
import subprocess
import shutil
import tempfile
from .. import loader, utils
logger = logging.getLogger(__name__)
@loader.tds
class Video2GIF(loader.Module):
"""Converts video to GIF"""
class Video2GIFMod(loader.Module):
"""Convert video to high quality GIF"""
strings = {
"name": "Video2GIF",
"conversion_success": "🎉 The conversion is completed!",
"conversion_error": "An error occurred when converting video to GIF.",
"not_video": "⚠️ Please reply to the message with the video or send the video in one message.",
"loading": "⏳ Conversion is underway",
"success": "✅ GIF created",
"error": "Conversion failed",
"no_video": "❌ Reply to a video",
"no_ffmpeg": "❌ FFmpeg not installed. Install: apt install ffmpeg",
"processing": "🔄 Processing video...",
"compressing": "📦 Optimizing GIF...",
}
strings_ru = {
"conversion_success": "🎉 Преобразование завершено!",
"conversion_error": "Произошла ошибка при преобразовании видео в GIF.",
"not_video": "⚠️ Пожалуйста, ответьте на сообщение с видео или отправьте видео одним сообщением.",
"loading": "⏳ Идет преобразование",
"success": "✅ GIF создан",
"error": "Ошибка конвертации",
"no_video": "❌ Ответьте на видео",
"no_ffmpeg": "❌ FFmpeg не установлен. Установите: apt install ffmpeg",
"processing": "🔄 Обрабатываю видео...",
"compressing": "📦 Оптимизирую GIF...",
}
def __init__(self):
self._ffmpeg_check = None
async def client_ready(self, client, db):
self._client = client
self._db = db
self._check_ffmpeg()
def _check_ffmpeg(self):
self._ffmpeg_check = shutil.which("ffmpeg") is not None
@loader.command(
ru_doc="[reply | в одном сообщении с видео] конвертирует видео в GIF.",
en_doc="[reply | in one message with video] — Converts video to GIF.",
ru_doc="[ответ] [fps] [ширина] - конвертировать видео в GIF",
en_doc="[reply] [fps] [width] - convert video to GIF",
)
async def gifc(self, message):
video = await self.get_video_from_message(message)
"""Convert video to GIF"""
if not self._ffmpeg_check:
return await utils.answer(message, self.strings["no_ffmpeg"])
if not video:
await utils.answer(message, self.strings["not_video"])
return
reply = await message.get_reply_message()
if not reply or not reply.video:
return await utils.answer(message, self.strings["no_video"])
await utils.answer(message, self.strings["loading"])
video_path = await self.client.download_media(video)
gif_path = f"{os.path.splitext(video_path)[0]}.gif"
args = utils.get_args_raw(message).split()
fps = 15 if len(args) < 1 else min(int(args[0]), 30)
width = 480 if len(args) < 2 else min(int(args[1]), 1024)
msg = await utils.answer(message, self.strings["processing"])
try:
self.convert_video_to_gif(video_path, gif_path)
await message.client.send_file(
message.chat_id, gif_path, caption=self.strings["conversion_success"]
gif_path = await self._convert_to_gif(reply, fps, width)
await self._client.send_file(
message.chat_id,
gif_path,
caption=self.strings["success"],
reply_to=reply.id,
)
except Exception as e:
await utils.answer(message, self.strings["conversion_error"])
print(f"Error during conversion: {e}")
finally:
self.cleanup_temp_files(video_path, gif_path)
async def get_video_from_message(self, message):
"""Получает видео из сообщения."""
if reply := await message.get_reply_message():
return reply.video
return message.video
os.remove(gif_path)
await msg.delete()
def convert_video_to_gif(self, video_path: str, gif_path: str) -> None:
"""Конвертирует видео в GIF с улучшенными параметрами."""
command = [
"ffmpeg",
"-i",
video_path,
"-vf",
"fps=30,scale=640:-1:flags=lanczos",
"-c:v",
"gif",
gif_path,
]
subprocess.run(command, check=True)
except Exception:
await utils.answer(message, self.strings["error"])
def cleanup_temp_files(self, video_path: str, gif_path: str) -> None:
"""Удаляет временные файлы."""
for temp_file in [video_path, gif_path]:
if os.path.exists(temp_file):
os.remove(temp_file)
async def _convert_to_gif(self, reply, fps: int, width: int) -> str:
"""Convert video to optimized GIF"""
with tempfile.TemporaryDirectory() as tmpdir:
video_path = os.path.join(tmpdir, "video.mp4")
gif_path = os.path.join(tmpdir, "output.gif")
await reply.download_media(video_path)
cmd = [
"ffmpeg",
"-i",
video_path,
"-vf",
f"fps={fps},scale={width}:-1:flags=lanczos",
"-lavfi",
"[0:v]split[s0][s1];[s0]palettegen[p];[s1][p]paletteuse",
"-y",
gif_path,
]
proc = await asyncio.create_subprocess_exec(*cmd)
await proc.communicate()
return gif_path