Skip to content

Commit

Permalink
🐛(thumbnail) do not process thumbnail for video without video stream
Browse files Browse the repository at this point in the history
In somes cases video uploaded do not have a video stream. In that case,
we should not generate a thumbnail has there is nothing to process.
  • Loading branch information
lunika committed Nov 12, 2024
1 parent fd2cdf2 commit 9128a47
Show file tree
Hide file tree
Showing 6 changed files with 104 additions and 3 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ and this project adheres to

## [Unreleased]

### Fixed

- Do not process thumbnail for video without video stream

## [0.12.0] - 2024-11-12

### Changed
Expand Down
4 changes: 3 additions & 1 deletion src/django_peertube_runner_connector/transcode.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@ def _process_transcoding(video: Video, video_path: str, domain: str):

video.duration = get_video_stream_duration(video_path, existing_probe=probe)

video.thumbnailFilename = build_video_thumbnails(video=video, video_file=video_file)
video.thumbnailFilename = build_video_thumbnails(
video=video, video_file=video_file, existing_probe=probe
)
video.save()

logger.info("Video at %s and uuid %s created.", video_path, video.uuid)
Expand Down
7 changes: 6 additions & 1 deletion src/django_peertube_runner_connector/utils/thumbnail.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,17 @@
from django_peertube_runner_connector.models import Video, VideoFile
from django_peertube_runner_connector.storage import video_storage

from .ffprobe import get_video_stream
from .files import get_video_directory


def build_video_thumbnails(video=Video, video_file=VideoFile):
def build_video_thumbnails(video=Video, video_file=VideoFile, existing_probe=None):
"""Create a video thumbnails with ffmpeg and save it to a file."""
video_url = video_storage.url(video_file.filename)

if get_video_stream(video_url, existing_probe=existing_probe) is None:
return None

thumbnail_filename = get_video_directory(video, "thumbnail.jpg")

with tempfile.NamedTemporaryFile(suffix=".jpg") as temp_file:
Expand Down
71 changes: 71 additions & 0 deletions tests/tests_django_peertube_runner_connector/probe_response.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,3 +88,74 @@
},
},
}

probe_response_without_video_stream = {
"streams": [
{
"index": 0,
"codec_name": "aac",
"codec_long_name": "AAC (Advanced Audio Coding)",
"profile": "LC",
"codec_type": "audio",
"codec_tag_string": "mp4a",
"codec_tag": "0x6134706d",
"sample_fmt": "fltp",
"sample_rate": "32000",
"channels": 1,
"channel_layout": "mono",
"bits_per_sample": 0,
"id": "0x1",
"r_frame_rate": "0/0",
"avg_frame_rate": "0/0",
"time_base": "1/32000",
"start_pts": 0,
"start_time": "0.000000",
"duration_ts": 682251264,
"duration": "21320.352000",
"bit_rate": "126248",
"extradata_size": 2,
"disposition": {
"default": 1,
"dub": 0,
"original": 0,
"comment": 0,
"lyrics": 0,
"karaoke": 0,
"forced": 0,
"hearing_impaired": 0,
"visual_impaired": 0,
"clean_effects": 0,
"attached_pic": 0,
"timed_thumbnails": 0,
"captions": 0,
"descriptions": 0,
"metadata": 0,
"dependent": 0,
"still_image": 0,
},
"tags": {
"language": "und",
"handler_name": "SoundHandler",
"vendor_id": "[0][0][0][0]",
},
}
],
"format": {
"filename": "path/to/video.mp4",
"nb_streams": 1,
"nb_programs": 0,
"format_name": "mov,mp4,m4a,3gp,3g2,mj2",
"format_long_name": "QuickTime / MOV",
"start_time": "0.000000",
"duration": "21320.352000",
"size": "339980572",
"bit_rate": "127570",
"probe_score": 100,
"tags": {
"major_brand": "iso5",
"minor_version": "512",
"compatible_brands": "iso5iso6mp41",
"encoder": "Lavf59.27.100",
},
},
}
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,9 @@ def test_process_transcoding(
mock_duration.assert_called_with(
video_url, existing_probe=mock_probe.return_value
)
mock_thumbnails.assert_called_with(video=video, video_file=video_file)
mock_thumbnails.assert_called_with(
video=video, video_file=video_file, existing_probe=mock_probe.return_value
)
mock_transcoding.assert_called_with(
video=video,
video_file=video_file,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@
from django.test import TestCase

import ffmpeg
from tests_django_peertube_runner_connector.probe_response import (
probe_response,
probe_response_without_video_stream,
)

from django_peertube_runner_connector.factories import VideoFactory, VideoFileFactory
from django_peertube_runner_connector.storage import video_storage
Expand All @@ -31,8 +35,21 @@ def test_build_video_thumbnails(self, mock_run):
thumbnail_filename = build_video_thumbnails(
video=self.video,
video_file=self.video_file,
existing_probe=probe_response,
)

mock_run.assert_called_once()
self.assertEqual(thumbnail_filename, self.thumbnail_filename)
self.assertTrue(video_storage.exists(thumbnail_filename))

@patch.object(ffmpeg, "run")
def test_build_video_thumbnails_with_no_video_stream(self, mock_run):
"""Should create a thumbnail file."""
thumbnail_filename = build_video_thumbnails(
video=self.video,
video_file=self.video_file,
existing_probe=probe_response_without_video_stream,
)

mock_run.assert_not_called()
self.assertIsNone(thumbnail_filename)

0 comments on commit 9128a47

Please sign in to comment.