Skip to content

Commit 2f8ae84

Browse files
committed
[Validator] Add Video constraint for validating video files
1 parent 6872b7d commit 2f8ae84

File tree

2 files changed

+319
-0
lines changed

2 files changed

+319
-0
lines changed

reference/constraints/Video.rst

Lines changed: 318 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,318 @@
1+
Video
2+
=====
3+
4+
Validates that a file is a valid video that meets certain constraints (width, height,
5+
aspect ratio, etc.). It extends the :doc:`File </reference/constraints/File>` constraint
6+
and adds video-specific validation options.
7+
8+
.. versionadded:: 7.4
9+
10+
The ``Video`` constraint was introduced in Symfony 7.4.
11+
12+
========== ===================================================================
13+
Applies to :ref:`property or method <validation-property-target>`
14+
Class :class:`Symfony\\Component\\Validator\\Constraints\\Video`
15+
Validator :class:`Symfony\\Component\\Validator\\Constraints\\VideoValidator`
16+
========== ===================================================================
17+
18+
Basic Usage
19+
-----------
20+
21+
This constraint is most commonly used on a property that stores a video file as a
22+
:class:`Symfony\\Component\\HttpFoundation\\File\\File` object. For example, suppose
23+
you're creating a video platform and want to validate uploaded video files::
24+
25+
// src/Entity/VideoContent.php
26+
namespace App\Entity;
27+
28+
use Symfony\Component\HttpFoundation\File\File;
29+
use Symfony\Component\Validator\Constraints as Assert;
30+
31+
class VideoContent
32+
{
33+
#[Assert\Video(
34+
maxWidth: 1920,
35+
maxHeight: 1080,
36+
maxSize: '100M',
37+
mimeTypes: ['video/mp4', 'video/webm'],
38+
)]
39+
private File $videoFile;
40+
}
41+
42+
.. caution::
43+
44+
This constraint requires the ``ffprobe`` binary to be installed and accessible
45+
on your system. The constraint uses ``ffprobe`` to extract video metadata.
46+
You can install it as part of the `FFmpeg package`_.
47+
48+
Options
49+
-------
50+
51+
``allowedCodecs``
52+
~~~~~~~~~~~~~~~~~
53+
54+
**type**: ``array`` **default**: ``['h264', 'hevc', 'h265', 'vp9', 'av1', 'mpeg4', 'mpeg2video']``
55+
56+
Defines which `video codecs`_ are allowed. If the video uses a codec not in this
57+
list, validation will fail::
58+
59+
// src/Entity/VideoContent.php
60+
namespace App\Entity;
61+
62+
use Symfony\Component\Validator\Constraints as Assert;
63+
64+
class VideoContent
65+
{
66+
#[Assert\Video(
67+
allowedCodecs: ['h264', 'hevc'],
68+
)]
69+
private $videoFile;
70+
}
71+
72+
``allowedContainers``
73+
~~~~~~~~~~~~~~~~~~~~~
74+
75+
**type**: ``array`` **default**: ``['mp4', 'mov', 'mkv', 'webm', 'avi']``
76+
77+
Defines which `video container formats`_ are allowed::
78+
79+
// src/Entity/VideoContent.php
80+
namespace App\Entity;
81+
82+
use Symfony\Component\Validator\Constraints as Assert;
83+
84+
class VideoContent
85+
{
86+
#[Assert\Video(
87+
allowedContainers: ['mp4', 'webm'],
88+
)]
89+
private $videoFile;
90+
}
91+
92+
``allowLandscape``
93+
~~~~~~~~~~~~~~~~~~
94+
95+
**type**: ``boolean`` **default**: ``true``
96+
97+
If set to ``false``, the video cannot be landscape oriented (i.e., the width
98+
cannot be greater than the height).
99+
100+
``allowPortrait``
101+
~~~~~~~~~~~~~~~~~
102+
103+
**type**: ``boolean`` **default**: ``true``
104+
105+
If set to ``false``, the video cannot be portrait oriented (i.e., the width
106+
cannot be less than the height).
107+
108+
``allowSquare``
109+
~~~~~~~~~~~~~~~
110+
111+
**type**: ``boolean`` **default**: ``true``
112+
113+
If set to ``false``, the video cannot be a square (i.e., the width and height
114+
cannot be equal).
115+
116+
``maxHeight``
117+
~~~~~~~~~~~~~
118+
119+
**type**: ``integer``
120+
121+
If set, the height of the video file must be less than or equal to this value
122+
in pixels.
123+
124+
``maxRatio``
125+
~~~~~~~~~~~~
126+
127+
**type**: ``float``
128+
129+
If set, the aspect ratio (``width / height``) of the video file must be less
130+
than or equal to this value. For example, a square video has a ratio of 1,
131+
a 16:9 video has a ratio of 1.78, and a 4:3 video has a ratio of 1.33.
132+
133+
``maxWidth``
134+
~~~~~~~~~~~~
135+
136+
**type**: ``integer``
137+
138+
If set, the width of the video file must be less than or equal to this value
139+
in pixels.
140+
141+
``minHeight``
142+
~~~~~~~~~~~~~
143+
144+
**type**: ``integer``
145+
146+
If set, the height of the video file must be greater than or equal to this
147+
value in pixels.
148+
149+
``minPixels``
150+
~~~~~~~~~~~~~
151+
152+
**type**: ``float``
153+
154+
If set, the total number of pixels (``width * height``) of the video file must be greater
155+
than or equal to this value.
156+
157+
``maxPixels``
158+
~~~~~~~~~~~~~
159+
160+
**type**: ``float``
161+
162+
If set, the total number of pixels (``width * height``) of the video file must be less
163+
than or equal to this value.
164+
165+
``minRatio``
166+
~~~~~~~~~~~~
167+
168+
**type**: ``float``
169+
170+
If set, the aspect ratio (``width / height``) of the video file must be greater
171+
than or equal to this value.
172+
173+
``minWidth``
174+
~~~~~~~~~~~~
175+
176+
**type**: ``integer``
177+
178+
If set, the width of the video file must be greater than or equal to this value
179+
in pixels.
180+
181+
``mimeTypes``
182+
~~~~~~~~~~~~~
183+
184+
**type**: ``array`` or ``string`` **default**: ``video/*``
185+
186+
See the :ref:`File mimeTypes option <reference-constraint-file-mime-types>` for a
187+
description of this option and a list of common video MIME types.
188+
189+
.. include:: /reference/constraints/_groups-option.rst.inc
190+
191+
.. include:: /reference/constraints/_payload-option.rst.inc
192+
193+
Messages
194+
--------
195+
196+
``allowLandscapeMessage``
197+
~~~~~~~~~~~~~~~~~~~~~~~~~
198+
199+
**type**: ``string`` **default**: ``The video is landscape oriented ({{ width }}x{{ height }}px). Landscape oriented videos are not allowed.``
200+
201+
The message displayed if the video is landscape oriented and landscape videos
202+
are not allowed.
203+
204+
``allowPortraitMessage``
205+
~~~~~~~~~~~~~~~~~~~~~~~~
206+
207+
**type**: ``string`` **default**: ``The video is portrait oriented ({{ width }}x{{ height }}px). Portrait oriented videos are not allowed.``
208+
209+
The message displayed if the video is portrait oriented and portrait videos are not allowed.
210+
211+
``allowSquareMessage``
212+
~~~~~~~~~~~~~~~~~~~~~~
213+
214+
**type**: ``string`` **default**: ``The video is square ({{ width }}x{{ height }}px). Square videos are not allowed.``
215+
216+
The message displayed if the video is square and square videos are not allowed.
217+
218+
``corruptedMessage``
219+
~~~~~~~~~~~~~~~~~~~~
220+
221+
**type**: ``string`` **default**: ``The video file is corrupted.``
222+
223+
The message displayed if the video file is corrupted and cannot be read by ``ffprobe``.
224+
225+
``maxHeightMessage``
226+
~~~~~~~~~~~~~~~~~~~~
227+
228+
**type**: ``string`` **default**: ``The video height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.``
229+
230+
The message displayed if the height of the video exceeds ``maxHeight``.
231+
232+
``maxPixelsMessage``
233+
~~~~~~~~~~~~~~~~~~~~
234+
235+
**type**: ``string`` **default**: ``The video has too many pixels ({{ pixels }} pixels). Maximum amount expected is {{ max_pixels }} pixels.``
236+
237+
The message displayed if the total number of pixels of the video exceeds ``maxPixels``.
238+
239+
``maxRatioMessage``
240+
~~~~~~~~~~~~~~~~~~~
241+
242+
**type**: ``string`` **default**: ``The video ratio is too big ({{ ratio }}). Allowed maximum ratio is {{ max_ratio }}.``
243+
244+
The message displayed if the aspect ratio of the video exceeds ``maxRatio``.
245+
246+
``maxWidthMessage``
247+
~~~~~~~~~~~~~~~~~~~
248+
249+
**type**: ``string`` **default**: ``The video width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.``
250+
251+
The message displayed if the width of the video exceeds ``maxWidth``.
252+
253+
``mimeTypesMessage``
254+
~~~~~~~~~~~~~~~~~~~~
255+
256+
**type**: ``string`` **default**: ``This file is not a valid video.``
257+
258+
See the :ref:`File mimeTypesMessage option <reference-constraint-file-mime-types-message>`.
259+
260+
``minHeightMessage``
261+
~~~~~~~~~~~~~~~~~~~~
262+
263+
**type**: ``string`` **default**: ``The video height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.``
264+
265+
The message displayed if the height of the video is less than ``minHeight``.
266+
267+
``minPixelsMessage``
268+
~~~~~~~~~~~~~~~~~~~~
269+
270+
**type**: ``string`` **default**: ``The video has too few pixels ({{ pixels }} pixels). Minimum amount expected is {{ min_pixels }} pixels.``
271+
272+
The message displayed if the total number of pixels of the video is less than ``minPixels``.
273+
274+
``minRatioMessage``
275+
~~~~~~~~~~~~~~~~~~~
276+
277+
**type**: ``string`` **default**: ``The video ratio is too small ({{ ratio }}). Minimum ratio expected is {{ min_ratio }}.``
278+
279+
The message displayed if the aspect ratio of the video is less than ``minRatio``.
280+
281+
``minWidthMessage``
282+
~~~~~~~~~~~~~~~~~~~
283+
284+
**type**: ``string`` **default**: ``The video width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.``
285+
286+
The message displayed if the width of the video is less than ``minWidth``.
287+
288+
``multipleVideoStreamsMessage``
289+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
290+
291+
**type**: ``string`` **default**: ``The video contains multiple streams. Only one stream is allowed.``
292+
293+
The message displayed if the video file contains multiple video streams.
294+
295+
``sizeNotDetectedMessage``
296+
~~~~~~~~~~~~~~~~~~~~~~~~~~
297+
298+
**type**: ``string`` **default**: ``The size of the video could not be detected.``
299+
300+
The message displayed if ffprobe cannot detect the dimensions of the video.
301+
302+
``unsupportedCodecMessage``
303+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
304+
305+
**type**: ``string`` **default**: ``Unsupported video codec "{{ codec }}".``
306+
307+
The message displayed if the video uses a codec that is not in the ``allowedCodecs`` list.
308+
309+
``unsupportedContainerMessage``
310+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
311+
312+
**type**: ``string`` **default**: ``Unsupported video container "{{ container }}".``
313+
314+
The message displayed if the video uses a container format that is not in the ``allowe
315+
316+
.. _`FFmpeg package`: https://ffmpeg.org/
317+
.. _`video codecs`: https://en.wikipedia.org/wiki/Comparison_of_video_codecs
318+
.. _`video container formats`: https://en.wikipedia.org/wiki/Comparison_of_video_container_formats

reference/constraints/map.rst.inc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ File Constraints
8888

8989
* :doc:`File </reference/constraints/File>`
9090
* :doc:`Image </reference/constraints/Image>`
91+
* :doc:`Video </reference/constraints/Video>`
9192

9293
Financial and other Number Constraints
9394
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

0 commit comments

Comments
 (0)