mirror of
https://github.com/lrnselfreliance/wrolpi.git
synced 2026-10-26 10:51:36 -04:00
Trimming video file name to avoid error when file name is too long.
This commit is contained in:
parent
37ff1ab2cd
commit
cdc73d9d16
13 changed files with 140 additions and 27 deletions
|
|
@ -8,12 +8,14 @@ import argparse
|
|||
import asyncio
|
||||
import difflib
|
||||
import functools
|
||||
import os.path
|
||||
import re
|
||||
import sys
|
||||
from difflib import SequenceMatcher
|
||||
from typing import List, Generator, Optional, Dict
|
||||
|
||||
from modules.videos.models import Video, Channel
|
||||
from modules.videos.lib import parse_video_file_name
|
||||
from modules.videos.models import Video, Channel
|
||||
from wrolpi.common import get_relative_to_media_directory, chain
|
||||
from wrolpi.db import get_db_curs, get_db_session
|
||||
from wrolpi.files.models import FileGroup
|
||||
|
|
@ -95,6 +97,8 @@ async def rank_video_quality(video: Video, sizes_by_source_id: Dict[str, int]) -
|
|||
rank += 2
|
||||
if video_file_matches_channel_info_json(video):
|
||||
rank += 2
|
||||
if video.get_comments():
|
||||
rank += 2
|
||||
# These are more common.
|
||||
if video.channel_id:
|
||||
rank += 1
|
||||
|
|
@ -124,7 +128,7 @@ async def rank_video_quality(video: Video, sizes_by_source_id: Dict[str, int]) -
|
|||
|
||||
def delete_video(video_id: int):
|
||||
with get_db_session(commit=True) as session:
|
||||
video = session.query(Video).filter_by(id=video_id).one()
|
||||
video: Video = session.query(Video).filter_by(id=video_id).one()
|
||||
video.delete()
|
||||
|
||||
|
||||
|
|
@ -183,12 +187,29 @@ async def handle_user_delete_duplicates(similar_videos: List[Video], video_url:
|
|||
if all_changes.isdigit():
|
||||
print(f'\nSkipping {similar_videos[0]} and similar because they are parts')
|
||||
return
|
||||
if delete_lower_ranked_automatically and any(PART_MATCH.match(i.file_group.title) for i in similar_videos):
|
||||
# "Part" detection is far too inaccurate, do not delete part videos.
|
||||
print(f'\nSkipping {similar_videos[0]} and similar because they may be parts')
|
||||
return
|
||||
|
||||
# Preserve the largest duplicate video.
|
||||
sizes_by_source_id = largest_size_by_source_id(similar_videos)
|
||||
|
||||
print('\n')
|
||||
ranked_videos = [(await rank_video_quality(i, sizes_by_source_id), i) for i in similar_videos]
|
||||
# Largest video gets a rank bump.
|
||||
largest_video_idx = None
|
||||
largest_video_size = None
|
||||
for idx, video in enumerate([i[1] for i in ranked_videos]):
|
||||
if largest_video_size and video.file_group.size > largest_video_size:
|
||||
largest_video_idx = idx
|
||||
largest_video_size = video.file_group.size
|
||||
else:
|
||||
largest_video_idx = idx
|
||||
largest_video_size = video.file_group.size
|
||||
ranked_videos[largest_video_idx] = \
|
||||
(ranked_videos[largest_video_idx][0] + 1, ranked_videos[largest_video_idx][1])
|
||||
# Order videos by rank, then size.
|
||||
ranked_videos = sorted(ranked_videos, key=lambda i: (i[0], i[1].file_group.size), reverse=True)
|
||||
for rank, video in ranked_videos:
|
||||
fg = video.file_group
|
||||
|
|
@ -212,13 +233,17 @@ async def handle_user_delete_duplicates(similar_videos: List[Video], video_url:
|
|||
index = similar_videos.index(lowest_video)
|
||||
del similar_videos[index]
|
||||
continue
|
||||
response = input('Delete the lowest ranked video? (y/N)').lower()
|
||||
response = input('Delete the lowest ranked video? Merge? (y/m/N)').lower()
|
||||
if response == 'y':
|
||||
# Don't need to confirm when the video has been ranked low.
|
||||
delete_video(lowest_video.id)
|
||||
index = similar_videos.index(lowest_video)
|
||||
del similar_videos[index]
|
||||
elif response == 'n':
|
||||
elif response == 'm':
|
||||
success = await handle_merge(ranked_videos)
|
||||
if success:
|
||||
break
|
||||
elif response == 'n' or response == '':
|
||||
break
|
||||
elif response == 'c':
|
||||
raise SkipChannel()
|
||||
|
|
@ -237,6 +262,47 @@ async def handle_user_delete_duplicates(similar_videos: List[Video], video_url:
|
|||
raise SkipChannel()
|
||||
|
||||
|
||||
async def handle_merge(videos: List[tuple[int, Video]]) -> bool | None:
|
||||
"""Replace the video file of Video with better data. Delete all other Videos."""
|
||||
response = input(
|
||||
'Keep which video file? Empty will replace largest video with best rank. (starting at 0..., n to skip)')
|
||||
if response == 'n':
|
||||
return
|
||||
if response == '':
|
||||
# Largest Video.
|
||||
keep_video = sorted(videos, key=lambda i: i[1].video_path.stat().st_size, reverse=True)[0][1]
|
||||
# Highest ranked video.
|
||||
keep_data = videos[0][1]
|
||||
else:
|
||||
if not response.isdigit() or ((keep_video := int(response)) and keep_video > len(videos) - 1):
|
||||
print('Invalid file index', file=sys.stderr)
|
||||
return
|
||||
if len(videos) == 2:
|
||||
keep_data = 0 if keep_video == 1 else 1
|
||||
else:
|
||||
response = input('Keep which video data? (starting at 0..., n to skip)')
|
||||
if response == 'n':
|
||||
return
|
||||
if not response.isdigit() or ((keep_data := int(response)) and keep_data > len(videos) - 1):
|
||||
print('Invalid file index', file=sys.stderr)
|
||||
return
|
||||
keep_video = videos[keep_video][1]
|
||||
keep_data = videos[keep_data][1]
|
||||
if keep_video == keep_data:
|
||||
print('Cannot keep and delete same video', file=sys.stderr),
|
||||
return
|
||||
# Replace video file of Video with better metadata.
|
||||
print(f'{keep_video.video_path} -> {keep_data.video_path}')
|
||||
os.replace(keep_video.video_path, keep_data.video_path)
|
||||
|
||||
for _, video in videos:
|
||||
if video.id != keep_data.id:
|
||||
delete_video(video.id)
|
||||
keep_data.validate()
|
||||
|
||||
return True
|
||||
|
||||
|
||||
async def main(channel_id: int = None, minimum_rank: float = MINIMUM_RANK, video_url: str = None,
|
||||
directory: str = None, delete_lower_ranked_automatically: bool = False):
|
||||
with get_db_curs() as curs:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue