Only updating view counts for videos that do not have a view count, and have a channel with info_json.

This commit is contained in:
Roland 2021-11-11 16:24:40 -07:00
parent 2585149efe
commit 165979f80a
No known key found for this signature in database
GPG key ID: 9D6DBD3ACF11AB93
3 changed files with 51 additions and 6 deletions

View file

@ -434,6 +434,11 @@ def get_video_duration(video_path: Path) -> int:
"""
Get the duration of a video in seconds. Do this using ffprobe.
"""
if not isinstance(video_path, Path):
video_path = Path(video_path)
if not video_path.is_file():
raise FileNotFoundError(f'{video_path} does not exist!')
cmd = ['/usr/bin/ffprobe', '-v', 'error', '-show_entries', 'format=duration', '-of',
'default=noprint_wrappers=1:nokey=1', str(video_path)]
@ -458,12 +463,20 @@ async def get_bulk_video_info_json(video_ids: List[int]):
for video_id in video_ids:
video = session.query(Video).filter_by(id=video_id).one()
logger.debug(f'Getting video info_json data: {video}')
video_path = get_absolute_video_path(video)
try:
info_json = video.get_info_json()
video.view_count = info_json.get('view_count') if info_json else None
video.duration = info_json.get('duration') if info_json else get_video_duration(video_path)
if info_json:
if not video.view_count and info_json.get('view_count'):
video.view_count = info_json['view_count']
if not video.duration:
# Get duration from info_json without reading video file.
video.duration = info_json.get('duration')
elif not video.duration:
# As a last resort, get duration from the video file.
video_path = get_absolute_video_path(video)
video.duration = get_video_duration(video_path)
except Exception:
logger.warning(f'Unable to get meta data of {video}', exc_info=True)
logger.info('Done getting video info_json meta data.')

View file

@ -80,8 +80,14 @@ def refresh_channel_info_json() -> bool:
Fill in Video columns that are extracted from the info_json.
"""
with get_db_curs() as curs:
query = 'SELECT id FROM video WHERE video_path IS NOT NULL AND ' \
'(duration IS NULL OR view_count IS NULL)'
query = '''
SELECT v.id
FROM video v
WHERE
v.video_path IS NOT NULL
AND v.info_json_path IS NOT NULL
AND (v.duration IS NULL OR v.view_count IS NULL)
'''
curs.execute(query)
missing_duration = [i for (i,) in curs.fetchall()]

View file

@ -1,4 +1,5 @@
import pathlib
import subprocess
import tempfile
from unittest import mock
from unittest.mock import Mock
@ -11,8 +12,9 @@ from modules.videos.test.common import create_channel_structure
from wrolpi.common import get_absolute_media_path
from wrolpi.db import get_db_session
from wrolpi.test.common import ExtendedTestCase, build_test_directories, wrap_test_db
from wrolpi.vars import PROJECT_DIR
from ..common import get_matching_directories, convert_image, bulk_validate_posters, remove_duplicate_video_paths, \
update_view_count
update_view_count, get_video_duration
class TestCommon(ExtendedTestCase):
@ -53,6 +55,22 @@ class TestCommon(ExtendedTestCase):
matches = get_matching_directories(temp_dir / 'foo')
assert matches == [str(temp_dir / 'foo/qux')]
def test_get_video_duration(self):
"""
Video duration can be retrieved from the video file.
"""
video_path = PROJECT_DIR / 'test/videos/wrolpi/big_buck_bunny_720p_1mb.mp4'
self.assertEqual(get_video_duration(video_path), 5)
video_path = PROJECT_DIR / 'test/videos/wrolpi/does not exist.mp4'
self.assertRaises(FileNotFoundError, get_video_duration, video_path)
video_path = str(PROJECT_DIR / 'test/videos/wrolpi/does not exist.mp4')
self.assertRaises(FileNotFoundError, get_video_duration, video_path)
with tempfile.NamedTemporaryFile() as fh:
self.assertRaises(subprocess.CalledProcessError, get_video_duration, fh.name)
@pytest.mark.parametrize(
'paths,expected',
@ -251,3 +269,11 @@ def test_update_view_count(tempdir: pathlib.Path):
# All videos are updated.
update_view_count(channel3.id)
check_view_counts({'vid1.mp4': 10, 'vid2.mp4': 11, 'vid3.mp4': 13, 'vid4.mp4': 14})
# An outdated view count will be overwritten.
with get_db_session(commit=True) as session:
vid = session.query(Video).filter_by(id=1).one()
vid.view_count = 8
check_view_counts({'vid1.mp4': 8, 'vid2.mp4': 11, 'vid3.mp4': 13, 'vid4.mp4': 14})
update_view_count(channel1.id)
check_view_counts({'vid1.mp4': 10, 'vid2.mp4': 11, 'vid3.mp4': 13, 'vid4.mp4': 14})