mirror of
https://github.com/lrnselfreliance/wrolpi.git
synced 2026-10-26 02:48:38 -04:00
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:
parent
2585149efe
commit
165979f80a
3 changed files with 51 additions and 6 deletions
|
|
@ -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.')
|
||||
|
|
|
|||
|
|
@ -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()]
|
||||
|
||||
|
|
|
|||
|
|
@ -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})
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue