1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
|
import os
from datetime import timedelta
import pytest
from lektor_ng.utils import locate_executable
from lektor_ng.videotools import Dimensions, get_ffmpeg_quality, get_timecode
has_ffmpeg = locate_executable("ffmpeg")
has_ffprobe = locate_executable("ffprobe")
require_ffmpeg = pytest.mark.skipif(not has_ffmpeg or not has_ffprobe, reason="requires ffmpeg and ffprobe in path")
@pytest.mark.parametrize(
"td, tc",
[
(timedelta(), "00:00:00"),
(timedelta(seconds=1), "00:00:01"),
(timedelta(seconds=1.5), "00:00:01.5"),
(timedelta(hours=8, minutes=15), "08:15:00"),
(timedelta(hours=36, minutes=35, seconds=34.25), "36:35:34.25"),
],
)
def test_get_timecode(td, tc):
assert get_timecode(td) == tc
@pytest.mark.parametrize(
"in_quality, out_quality",
[
(0, 31),
(100, 2),
],
)
def test_get_ffmpeg_quality(in_quality, out_quality):
assert get_ffmpeg_quality(in_quality) == out_quality
@pytest.mark.parametrize(
"in_quality",
[
-1,
101,
],
)
def test_get_ffmpeg_quality_bad_range(in_quality):
with pytest.raises(ValueError):
get_ffmpeg_quality(in_quality)
@pytest.mark.parametrize(
"dim, ar",
[
(Dimensions(100, 100), 1),
(Dimensions(320, 160), 2),
(Dimensions(160, 320), 0.5),
],
)
def test_dimensions_aspect_ratio(dim, ar):
assert dim.aspect_ratio == ar
@pytest.mark.parametrize(
"source, target, upscale, rescale",
[
((100, 100), (50, None), None, (50, 50)),
((100, 50), (50, None), None, (50, 25)),
((100, 50), (None, 25), None, (50, 25)),
],
)
def test_dimensions_fit_within(source, target, upscale, rescale):
# We don't take a crop parameter here since it will always be the same as
# rescale
source = Dimensions(*source)
target_width, target_height = target
rescale = Dimensions(*rescale)
new_dims = source.fit_within(target_width, target_height, upscale)
assert rescale == new_dims.rescale
assert rescale == new_dims.crop
@pytest.mark.parametrize(
"source, target, upscale, rescale, crop",
[
((100, 50), (25, 25), None, (50, 25), (25, 25)),
((100, 50), (100, 100), None, (200, 100), (100, 100)),
((100, 50), (100, 100), False, (100, 50), (100, 50)),
],
)
def test_dimensions_cover(source, target, upscale, rescale, crop):
source = Dimensions(*source)
target_width, target_height = target
rescale = Dimensions(*rescale)
crop = Dimensions(*crop)
new_dims = source.cover(target_width, target_height, upscale)
assert rescale == new_dims.rescale
assert crop == new_dims.crop
@pytest.mark.parametrize(
"source, target, upscale, rescale",
[
((100, 50), (25, 25), None, (25, 25)),
((100, 50), (100, 100), None, (100, 100)),
((100, 50), (100, 100), False, (100, 50)),
],
)
def test_dimensions_stretch(source, target, upscale, rescale):
# We don't take a crop parameter here since it will always be the same as
# rescale
source = Dimensions(*source)
target_width, target_height = target
rescale = Dimensions(*rescale)
new_dims = source.stretch(target_width, target_height, upscale)
assert rescale == new_dims.rescale
assert rescale == new_dims.crop
def test_dimensions_invalid_resize():
dim = Dimensions(640, 480)
with pytest.raises(ValueError):
dim.resize(mode="invalid")
@require_ffmpeg
def test_metadata(pad):
video = pad.root.attachments.videos.get("test.mp4")
assert video is not None
assert video.width == 320
assert video.height == 180
assert video.duration == timedelta(seconds=3)
@require_ffmpeg
def test_thumbnail_height(builder):
builder.build_all()
with open(os.path.join(builder.destination_path, "index.html"), encoding="utf-8") as f:
html = f.read()
# The first thumbnail has the same dimensions as the source video,
# seeked to 1.5 seconds in
assert '<img src="test@t00-00-01-5.jpg" width="320" height="180">' in html
# Thumbnail is half the original width, so its computed height is half.
assert '<img src="test@t00-00-00_160.jpg" width="160" height="90">' in html
# There should also be a square thumbnail
assert '<img src="test@t00-00-02_160x160_crop.jpg" width="160" height="160">' in html
|