Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add settings for fake video detection #204

Merged
merged 7 commits into from
Jul 4, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions src/frontend/src/app/settings/settings.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,28 @@
<button type="button" class="btn btn-xs btn-sm btn-outline-primary" (click)="sendTestNotification()">Send test notification <span class="oi oi-bolt"></span></button>
</div>
</div>
<!-- video detection -->
<div class="card">
<div class="card-header d-flex justify-content-between">
<span>Video Validation</span>
</div>
<div class="card-body">
<div>Automatically detect, blacklist, and retry <strong>fake</strong> videos.</div>
<div><span class="badge badge-dark">Note</span> This will also reject any bundled downloads (e.g. rar, tar, zip)</div>
<div class="form-check mt-2">
<input class="form-check-input" type="radio" [value]="true" formControlName="enable_video_detection" id="video-detection-true">
<label class="form-check-label" for="video-detection-true">
Enable
</label>
</div>
<div class="form-check">
<input class="form-check-input" type="radio" [value]="false" formControlName="enable_video_detection" id="video-detection-false">
<label class="form-check-label" for="video-detection-false">
Disable
</label>
</div>
</div>
</div>
</div>
<!-- import library -->
<div class="col-12 col-sm-6 col-md-4">
Expand Down
1 change: 1 addition & 0 deletions src/frontend/src/app/settings/settings.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ export class SettingsComponent implements OnInit, AfterContentChecked {
'quality_profile_tv': [settings['quality_profile_tv'], Validators.required],
'quality_profile_movies': [settings['quality_profile_movies'], Validators.required],
'allow_hardcoded_subs': [settings['allow_hardcoded_subs'], Validators.required],
'enable_video_detection': [settings['enable_video_detection'], Validators.required],
'exclusions': [settings['keyword_search_filters'] ? _.keys(settings['keyword_search_filters']) : []],
'language': [settings['language'], Validators.required],
'users': new FormArray([]),
Expand Down
10 changes: 5 additions & 5 deletions src/nefarious/importer/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ def ingest_path(self, file_path):
if file_extension_match:
# skip sample files
if parser.sample_file_regex.search(file_name):
logger_background.warning('[NO_MATCH_SAMPLE] Not matching sample file "{}"'.format(file_path))
logger_background.info('[NO_MATCH_SAMPLE] Not matching sample file "{}"'.format(file_path))
return False
title = parser.match['title']
if not title:
Expand All @@ -66,7 +66,7 @@ def ingest_path(self, file_path):
title = new_title
parser.match.update(parser_match)
else:
logger_background.warning('[NO_MATCH_TITLE] Could not match file without title "{}"'.format(file_path))
logger_background.info('[NO_MATCH_TITLE] Could not match file without title "{}"'.format(file_path))
return False
file_extension = file_extension_match.group()
if file_extension in video_extensions():
Expand All @@ -91,11 +91,11 @@ def ingest_path(self, file_path):
logger_background.info('[MATCH] Saved media "{}" from file "{}"'.format(watch_media, file_path))
return watch_media
else: # for/else
logger_background.warning('[NO_MATCH_MEDIA] No media match for title "{}" and file "{}"'.format(title, file_path))
logger_background.info('[NO_MATCH_MEDIA] No media match for title "{}" and file "{}"'.format(title, file_path))
else:
logger_background.warning('[NO_MATCH_VIDEO] No valid video file extension for file "{}"'.format(file_path))
logger_background.info('[NO_MATCH_VIDEO] No valid video file extension for file "{}"'.format(file_path))
else:
logger_background.warning('[NO_MATCH_EXTENSION] No file extension for file "{}"'.format(file_path))
logger_background.info('[NO_MATCH_EXTENSION] No file extension for file "{}"'.format(file_path))
else:
logger_background.info('[NO_MATCH_UNKNOWN] Unknown match for file "{}"'.format(file_path))
return False
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Generated by Django 3.0.2 on 2022-07-04 14:09

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('nefarious', '0069_auto_20211128_1337'),
]

operations = [
migrations.AddField(
model_name='nefarioussettings',
name='enable_fake_video_detection',
field=models.BooleanField(default=False),
),
]
22 changes: 22 additions & 0 deletions src/nefarious/migrations/0071_auto_20220704_2043.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Generated by Django 3.0.2 on 2022-07-04 20:43

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('nefarious', '0070_nefarioussettings_enable_fake_video_detection'),
]

operations = [
migrations.RemoveField(
model_name='nefarioussettings',
name='enable_fake_video_detection',
),
migrations.AddField(
model_name='nefarioussettings',
name='enable_video_detection',
field=models.BooleanField(default=True),
),
]
4 changes: 4 additions & 0 deletions src/nefarious/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,12 @@ class NefariousSettings(models.Model):
quality_profile_tv = models.CharField(max_length=500, default=quality.PROFILE_ANY.name, choices=zip(quality.PROFILE_NAMES, quality.PROFILE_NAMES))
quality_profile_movies = models.CharField(max_length=500, default=quality.PROFILE_HD_720P_1080P.name, choices=zip(quality.PROFILE_NAMES, quality.PROFILE_NAMES))

# whether to allow hardcoded subtitles
allow_hardcoded_subs = models.BooleanField(default=False)

# whether to enable video detection features (e.g. fake)
enable_video_detection = models.BooleanField(default=False)

# expects keyword/boolean pairs like {"x265": false, "265": false}
keyword_search_filters = JSONField(blank=True, null=True) # type: dict

Expand Down
11 changes: 7 additions & 4 deletions src/nefarious/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -159,18 +159,21 @@ def completed_media_task():

logger_background.info('Media completed: {}'.format(media))

# run video detection on the relevant video files for movies
if isinstance(media, WatchMovie):
# run video detection, if enabled, on the relevant video files for movies, staging_path
if nefarious_settings.enable_video_detection and isinstance(media, WatchMovie):
logger_background.info("[VIDEO_DETECTION] verifying '{}'".format(media))
staging_path = os.path.join(
settings.INTERNAL_DOWNLOAD_PATH,
settings.UNPROCESSED_PATH,
nefarious_settings.transmission_movie_download_dir.lstrip('/'),
torrent.name,
)
try:
if not VideoDetect.has_valid_video_in_path(staging_path):
if VideoDetect.has_valid_video_in_path(staging_path):
logger_background.info("[VIDEO_DETECTION] '{}' has valid video files".format(media))
else:
blacklist_media_and_retry(media)
logger_background.error("Blacklisting video '{}' because no valid video was found: {}".format(media, staging_path))
logger_background.error("[VIDEO_DETECTION] blacklisting '{}' because no valid video was found: {}".format(media, staging_path))
continue
except Exception as e:
logger_background.exception(e)
Expand Down
7 changes: 3 additions & 4 deletions src/nefarious/video_detection.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,7 @@ def __init__(self, video_path: str):

@classmethod
def has_valid_video_in_path(cls, path: str):
# TODO - remove once fixed bug https://github.com/lardbit/nefarious/issues/203
return True
# TODO - this doesn't handle bundles (rar/zip/tar etc) since it won't find any "media" files

files_to_verify = []

Expand Down Expand Up @@ -65,8 +64,8 @@ def has_valid_video_in_path(cls, path: str):
return True
return False

def is_correct_length(self, correct_duration: float):
return abs(self.duration - correct_duration) / correct_duration < self.MAX_VIDEO_DURATION_DIFFERENCE_RATIO
def is_correct_length(self, expected_duration: float):
return abs(self.duration - expected_duration) / expected_duration < self.MAX_VIDEO_DURATION_DIFFERENCE_RATIO

def is_too_similar(self):
return self.video_similarity_std <= self.MIN_VIDEO_SIMILARITY_STD
Expand Down