From 3c07500ec0bc788c46a58bad2ac7417cd5978736 Mon Sep 17 00:00:00 2001 From: blank X Date: Sat, 9 Oct 2021 20:06:59 +0700 Subject: [PATCH] Add video attributes --- redditbot.py | 39 ++++++++++++++++++++++++++++++++++----- 1 file changed, 34 insertions(+), 5 deletions(-) diff --git a/redditbot.py b/redditbot.py index fcbff13..3ea0656 100644 --- a/redditbot.py +++ b/redditbot.py @@ -9,6 +9,7 @@ import tempfile import functools import mimetypes import traceback +from decimal import Decimal from itertools import zip_longest from urllib.parse import urlparse, urlunparse, urljoin import yaml @@ -18,6 +19,7 @@ import aiocron from bs4 import BeautifulSoup from telethon import TelegramClient, events from telethon.utils import chunks, is_list_like +from telethon.tl.types import DocumentAttributeVideo mimetypes.init(['mime.types']) with open('config.yaml') as file: @@ -193,11 +195,8 @@ async def main(): await add_chat(chat, send_to_chats[chat]) async def _start_broadcast(text, file, chats): - uploaded_files = [] - for i in file or []: - uploaded_files.append(await client.upload_file(i)) for chat in chats: - for i in chunks(zip_longest(text, uploaded_files), 10): + for i in chunks(zip_longest(text, file or []), 10): j, k = zip(*i) if not any(k): k = None @@ -207,7 +206,37 @@ async def main(): if len(j) == 1 and len(k) == 1: j = j[0] k = k[0] - await client.send_message(chat, j, file=k, link_preview=False) + attributes = [] + mimetype = await _get_file_mimetype(k) + if mimetype.startswith('video/'): + try: + data = await _get_video_data(k) + duration = int(Decimal(data['format']['duration'])) + w = h = None + for l in data['streams']: + if l['codec_type'] != 'video': + continue + w = l['width'] + h = l['height'] + break + except Exception: + logging.exception('Exception when getting video data') + else: + attributes.append(DocumentAttributeVideo(duration, w, h, supports_streaming=mimetype == 'video/mp4')) + await client.send_message(chat, j, file=k, link_preview=False, attributes=attributes) + + async def _get_video_data(filename): + proc = await asyncio.create_subprocess_exec('ffprobe', '-show_format', '-show_streams', '-print_format', 'json', filename, stdout=asyncio.subprocess.PIPE) + stdout, _ = await proc.communicate() + data = json.loads(stdout) + if data.get('format') and 'duration' not in data['format']: + with tempfile.NamedTemporaryFile() as tempf: + proc = await asyncio.create_subprocess_exec('ffmpeg', '-an', '-sn', '-i', filename, '-c', 'copy', '-f', 'matroska', tempf.name) + await proc.communicate() + ndata = await _get_video_data(tempf.name) + if ndata.get('format') and 'duration' in ndata['format']: + data['format']['duration'] = ndata['format']['duration'] + return data async def _download_file(filename, url): print(url)