wrolpi/modules/videos/captions.py
lrnselfreliance 86893ef7f1
Feature/video validate (#74)
* Videos are marked as validated so they will not be tried again.  All previous bulk methods are combined into one.

* Passing json to fixture factory to avoid writing the files in every test.

* Adding log to explain if refresh is slow.

* Generating video poster if one cannot be found.

* Generating video poster if no poster can be found.

* Videos without a video file (yet to be downloaded) are not validated.

* Video title is extracted from the video file name as a last resort.

* Keeping existing view count because it may be from the channel, which will be more recent.

* Downloads should only be downloaded after they are due, not the same day.

* Setting manager on new downloads.

* Checking if downloading is disabled in loop.

* Adding log when refresh is complete.

* Not generating posters by default.  This is to avoid deleting files.

* Not converting posters unless channel has that enabled.

* Not logging on valid because all posters will be checked.

* Validating videos in upsert.

* Using video name parser in upsert.

* Using validate_video in upsert so that data is only read once from disk.

* Attaching manager in download_manager.get_download.

* Adding 22 to preferred video format for odd 720p resolution.

Signed-off-by: Roland <roland@learningselfreliance.com>
2022-01-14 15:54:51 -07:00

65 lines
1.8 KiB
Python
Executable file

#! /usr/bin/env python3
import pathlib
from pathlib import Path
from typing import Generator, Union
import srt
import webvtt
from wrolpi.common import logger
from wrolpi.media_path import MediaPath
from .models import Video
def get_caption_text(caption_path: Union[str, Path]) -> Generator:
"""
Return all text from each caption of a caption file.
"""
if str(caption_path).endswith('vtt'):
for caption in webvtt.read(caption_path):
text = str(caption.text).strip()
yield text
else:
with open(caption_path, 'rt') as fh:
contents = fh.read()
for subtitle in srt.parse(contents):
yield subtitle.content
def get_unique_caption_lines(caption_path: Union[str, Path]) -> Generator:
"""
Return all unique lines from each caption of a caption file.
"""
last_line = None
for text in get_caption_text(caption_path):
for line in text.split('\n'):
if line and line != last_line:
last_line = line
yield line
def get_video_captions(video: Video):
"""
Parse video captions from the video's captions file.
"""
if isinstance(video.caption_path, MediaPath):
caption_path = video.caption_path.path
else:
caption_path = pathlib.Path(video.caption_path)
try:
lines = get_unique_caption_lines(str(caption_path))
block = '\n'.join(lines)
return block
except UnicodeDecodeError:
# Failed to decode the caption file
# TODO handle this error
pass
except webvtt.errors.MalformedFileError:
# File format is broken
pass
except webvtt.errors.MalformedCaptionError:
# Captions form is broken somehow
pass
logger.debug(f'Failed to parse caption file {caption_path}')