Handle audio stream in .mp4 container from .m3u8 (.ts)

This commit is contained in:
Taras Terletskyi 2023-06-26 21:16:11 +03:00
parent 9a5c149b9a
commit 3947551b66
4 changed files with 41 additions and 14 deletions

View file

@ -38,7 +38,7 @@ class BaseUploadContext(RealBaseModel):
class VideoUploadContext(BaseUploadContext):
height: StrictInt
width: StrictInt
thumb: StrictStr
thumb: StrictStr | None = None
class AudioUploadContext(BaseUploadContext):
@ -271,8 +271,10 @@ class VideoUploadTask(AbstractUploadTask):
'duration': int(self._media_ctx.duration),
'height': self._media_ctx.height,
'width': self._media_ctx.width,
'thumb': self._media_ctx.thumb,
}
if self._media_ctx.thumb:
kwargs['thumb'] = self._media_ctx.thumb
if self._media_ctx.type is MessageMediaType.ANIMATION:
kwargs['animation'] = self._media_ctx.filepath
return self._bot.send_animation(**kwargs)
@ -291,7 +293,11 @@ class VideoUploadTask(AbstractUploadTask):
self._media_ctx.type = message.media
self._media_ctx.filepath = video.file_id
self._media_ctx.thumb = video.thumbs[0].file_id
try:
self._media_ctx.thumb = video.thumbs[0].file_id
except TypeError:
# video.thumbs is None when no thumnmail
self._log.warning('No thumbnail found for caching object')
self._media_ctx.is_cached = True
self._cached_message = message

View file

@ -116,12 +116,12 @@ class MediaService:
coro_tasks = []
if not video.thumb_path:
thumb_path = os.path.join(media.root_path, video.thumb_name)
video.thumb_path = thumb_path
coro_tasks.append(
self._create_thumb_task(
file_path=video.filepath,
thumb_path=thumb_path,
duration=video.duration,
video_ctx=video,
)
)
@ -146,15 +146,21 @@ class MediaService:
file = results[0]
media.audio.orm_file_id = file.id
@staticmethod
async def _set_probe_ctx(video: Video) -> None:
async def _set_probe_ctx(self, video: Video) -> None:
probe_ctx = await GetFfprobeContextTask(video.filepath).run()
if not probe_ctx:
return
video_streams = [
stream for stream in probe_ctx['streams'] if stream['codec_type'] == 'video'
]
video_streams = [s for s in probe_ctx['streams'] if s['codec_type'] == 'video']
video.duration = float(probe_ctx['format']['duration'])
if not video_streams:
self._log.warning(
'Video file does not contain video stream. Might be only audio. '
'Ffprobe context: %s',
probe_ctx,
)
return
video.width = video_streams[0]['width']
video.height = video_streams[0]['height']
@ -169,10 +175,16 @@ class MediaService:
)
def _create_thumb_task(
self, file_path: str, thumb_path: str, duration: float
self,
file_path: str,
thumb_path: str,
duration: float,
video_ctx: Video,
) -> asyncio.Task:
return create_task(
MakeThumbnailTask(thumb_path, file_path, duration=duration).run(),
MakeThumbnailTask(
thumb_path, file_path, duration=duration, video_ctx=video_ctx
).run(),
task_name=MakeThumbnailTask.__class__.__name__,
logger=self._log,
exception_message='Task "%s" raised an exception',

View file

@ -1,3 +1,5 @@
from yt_shared.schemas.media import Video
from worker.core.config import settings
from worker.core.tasks.abstract import AbstractFfBinaryTask
@ -5,13 +7,19 @@ from worker.core.tasks.abstract import AbstractFfBinaryTask
class MakeThumbnailTask(AbstractFfBinaryTask):
_CMD = 'ffmpeg -y -loglevel error -i "{filepath}" -ss {time_point} -vframes 1 -q:v 7 "{thumbpath}"'
def __init__(self, thumbnail_path: str, *args, duration: float, **kwargs) -> None:
def __init__(
self, thumbnail_path: str, *args, duration: float, video_ctx: Video, **kwargs
) -> None:
super().__init__(*args, **kwargs)
self._thumbnail_path = thumbnail_path
self._duration = duration
self._video_ctx = video_ctx
async def run(self) -> bool:
return await self._make_thumbnail()
is_created = await self._make_thumbnail()
if is_created:
self._video_ctx.thumb_path = self._thumbnail_path
return is_created
async def _make_thumbnail(self) -> bool:
cmd = self._CMD.format(

View file

@ -18,7 +18,8 @@ RABBITMQ_PORT=5672
REDIS_HOST=yt_redis
LOG_LEVEL=INFO
TMP_DOWNLOAD_ROOT_PATH=/tmp/download_tmpfs
TMP_DOWNLOAD_DIR=downloading
TMP_DOWNLOADED_DIR=downloaded
LOG_LEVEL=INFO