Skip to content

Commit accc27d

Browse files
committed
### Added
- The `ffmpeg` progress for video transcoding is now written out to a `.progress` file - Added a `progress` controller to return video transcoding progress - Moved all of the default settings out to the `config.php` file
1 parent ca2a292 commit accc27d

File tree

11 files changed

+492
-63
lines changed

11 files changed

+492
-63
lines changed

CHANGELOG.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,12 @@
44
### Added
55
- Added `height` and `width` options for resizing the videos
66
- Added an `aspectRatio` option to control how aspect ratio scaling is done
7-
- Added an `letterboxColor` option
8-
- The `ffmpeg` progress for a particular video is now written out to a `.progress` file
7+
- Added a `letterboxColor` option
8+
- Added a `sharpen` option
99
- Added the `getFileInfo` variable to extract information from a video/audio file
10+
- The `ffmpeg` progress for video transcoding is now written out to a `.progress` file
11+
- Added a `progress` controller to return video transcoding progress
12+
- Moved all of the default settings out to the `config.php` file
1013

1114
### Fixed
1215
- Fixed some issues with the lockfile naming

LICENSE.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1-
The MIT License (MIT)
2-
1+
The Transcoder License
32
Copyright (c) 2017 nystudio107
43

5-
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4+
Permission is hereby granted, free of charge, to any person or entity obtaining a copy of this software and associated documentation files (the "Software"), to use the software in any capacity, including commercial and for-profit use. Permission is also granted to alter, modify, or extend the Software for your own use, or commission a third-party to perform modifications for you.
5+
6+
Permission is NOT granted to create derivative works, sublicense, and/or sell copies of the Software. This is not FOSS software.
67

78
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
89

README.md

Lines changed: 270 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,23 @@ Related: [Transcoder for Craft 2.x](https://github.com/nystudio107/transcoder)
88

99
To install Transcoder, follow these steps:
1010

11-
3. Install with Composer via `composer require nystudio107/craft3-transcoder`
12-
4. Install plugin in the Craft Control Panel under Settings > Plugins
11+
1. Install with Composer via `composer require nystudio107/craft3-transcoder`
12+
2. Install plugin in the Craft Control Panel under Settings > Plugins
1313

1414
Transcoder works on Craft 3.x.
1515

16+
You will also need [ffmpeg](https://ffmpeg.org/) installed for Transcoder to work. On Ubuntu 16.04, you can do just:
17+
18+
sudo apt-get update
19+
sudo apt-get install ffmpeg
20+
21+
To install `ffmpeg` on Centos 6/7, you can follow the guide [How to Install FFmpeg on CentOS](https://www.vultr.com/docs/how-to-install-ffmpeg-on-centos)
22+
23+
If you have managed hosting, contact your sysadmin to get `ffmpeg` installed.
24+
1625
## Transcoder Overview
1726

18-
The Transcoder video allows you to take any locally stored video, and transcode it into any bitrate/framerate, and save it out as a web-ready `.mp4` file.
27+
The Transcoder video allows you to take any locally stored video, and transcode it into any size, bitrate, framerate, and save it out as a web-ready `.mp4` file.
1928

2029
It also allows you to get a thumbnail of the video in any size and at any timecode.
2130

@@ -57,12 +66,43 @@ The only configuration for Transcoder is in the `config.php` file, which is a mu
5766
// The path to the ffmpeg binary
5867
"ffmpegPath" => "/usr/bin/ffmpeg",
5968

69+
// The path to the ffprobe binary
70+
"ffprobePath" => "/usr/bin/ffprobe",
71+
72+
// The options to use for ffprobe
73+
"ffprobeOptions" => "-v quiet -print_format json -show_format -show_streams",
74+
6075
// The path where the transcoded videos are stored
6176
"transcoderPath" => $_SERVER['DOCUMENT_ROOT'] . "/transcoder/",
6277

6378
// The URL where the transcoded videos are stored
6479
"transcoderUrl" => "/transcoder/",
6580

81+
// Default options for encoded videos
82+
"defaultVideoOptions" => [
83+
"fileSuffix" => ".mp4",
84+
"bitRate" => "800k",
85+
"frameRate" => 15,
86+
"width" => "",
87+
"height" => "",
88+
"sharpen" => true,
89+
// Can be "none", "crop", or "letterbox"
90+
"aspectRatio" => "letterbox",
91+
"letterboxColor" => "",
92+
],
93+
94+
// Default options for video thumbnails
95+
"defaultThumbnailOptions" => [
96+
"fileSuffix" => ".jpg",
97+
"timeInSecs" => 10,
98+
"width" => "",
99+
"height" => "",
100+
"sharpen" => true,
101+
// Can be "none", "crop", or "letterbox"
102+
"aspectRatio" => "letterbox",
103+
"letterboxColor" => "",
104+
],
105+
66106
];
67107

68108
## Using Transcoder
@@ -71,17 +111,21 @@ The only configuration for Transcoder is in the `config.php` file, which is a mu
71111

72112
To generate a transcoded video, do the following:
73113

74-
{% set transVideoUrl = craft.transcoder.getVideoUrl('/home/vagrant/sites/nystudio107/public/trimurti.mp4', {
114+
{% set transVideoUrl = craft.transcoder.getVideoUrl('/home/vagrant/sites/nystudio107/public/oceans.mp4', {
75115
"frameRate": 20,
76-
"bitRate": "500k"
116+
"bitRate": "500k",
117+
"width": 720,
118+
"height": 480
77119
}) %}
78120

79-
You can also pass in an `AssetFileModel`:
121+
You can also pass in an `Asset`:
80122

81123
{% set myAsset = entry.someAsset.first() %}
82124
{% set transVideoUrl = craft.transcoder.getVideoUrl(myAsset, {
83125
"frameRate": 20,
84-
"bitRate": "500k"
126+
"bitRate": "500k",
127+
"width": 720,
128+
"height": 480
85129
}) %}
86130

87131
It will return to you a URL to the transcoded video if it already exists, or if it doesn't exist, it will return `""` and kick off the transcoding process (which can be quite lengthy for long videos).
@@ -91,8 +135,12 @@ In the array you pass in, the default values are used if the key/value pair does
91135
{
92136
"bitRate" => "800k",
93137
"frameRate" => 15,
138+
"aspectRatio" => "letterbox",
139+
"sharpen" => true,
94140
}
95141

142+
These default values come from the `config.php` file.
143+
96144
If you want to have the Transcoder not change a parameter, pass in an empty value in the key/value pair, e.g.:
97145

98146
{% set transVideoUrl = craft.transcoder.getVideoUrl('/home/vagrant/sites/nystudio107/public/trimurti.mp4', {
@@ -102,11 +150,69 @@ If you want to have the Transcoder not change a parameter, pass in an empty valu
102150

103151
The above example would cause it to not change the frameRate or bitRate of the source movie (not recommended for client-proofing purposes).
104152

153+
The `aspectRatio` parameter lets you control how the video aspect ratio is maintained when it is scaled:
154+
155+
`none` results in the aspect ratio of the original video not being maintained, and the video scaled to the dimensions passed in:
156+
157+
![Screenshot](resources/screenshots/oceans_20s_300w_200h_none.jpg)
158+
159+
`crop` scales the video up to maintain the original aspect ratio, and then crops it so that it's full-frame:
160+
161+
![Screenshot](resources/screenshots/oceans_20s_300w_200h_crop.jpg)
162+
163+
`letterbox` scales the video to fit the new frame, putting a letterboxed or pillarboxed border to pad it:
164+
165+
![Screenshot](resources/screenshots/oceans_20s_300w_200h_letterbox.jpg)
166+
167+
You can control the color of the letterboxed area (it's `black` by default) via the `letterboxColor` option. It can be either a semantic color name, or a hexcode color, e.g.: `0xC0C0C0`
168+
169+
The `sharpen` option determines whether an unsharp mask filter should be applied to the scaled video.
170+
171+
### Getting Transcoding Progress
172+
173+
Transcoding of videos can take quite a bit of time, so Transcoder provides you with a way to get the status of any currently running transcoding operation via `craft.transcoder.getVideoProgressUrl()`. For example:
174+
175+
{% set myAsset = entry.someAsset.first() %}
176+
{% set videoOptions = {
177+
"frameRate": 60,
178+
"bitRate": "1000k",
179+
"width": 1000,
180+
"height": 800,
181+
"aspectRatio": "none",
182+
} %}
183+
{% set transVideoUrl = craft.transcoder.getVideoUrl(myAsset, videoOptions) %}
184+
{% set progressUrl = craft.transcoder.getVideoProgressUrl(myAsset, videoOptions) %}
185+
186+
The variable `progressUrl` in the example above is set to a URL will return a JSON array of data indicating the current progress of the transcoding:
187+
188+
{
189+
"filename": "oceans_1000kbps_60fps_1000w_800h_letterbox.mp4",
190+
"duration": 46.61,
191+
"time": 37.69,
192+
"progress": 81
193+
}
194+
195+
* `filename` - the name of the file
196+
* `duration` - the duration of the video/audio stream
197+
* `time` - the time of the current encoding
198+
* `progress` - a percentage indicating how much of the encoding is done
199+
200+
You can use this information to provide a progress bar via JavaScript or from a plugin.
201+
105202
### Generating a Video Thumbnail
106203

107204
To generate a thumbnail from a video, do the following:
108205

109-
{% set transVideoThumbUrl = craft.transcoder.getVideoThumbnailUrl('/home/vagrant/sites/nystudio107/public/trimurti.mp4', {
206+
{% set transVideoThumbUrl = craft.transcoder.getVideoThumbnailUrl('/home/vagrant/sites/nystudio107/public/oceans.mp4', {
207+
"width": 300,
208+
"height": 200,
209+
"timeInSecs": 20,
210+
}) %}
211+
212+
You can also pass in an `Asset`:
213+
214+
{% set myAsset = entry.someAsset.first() %}
215+
{% set transVideoUrl = craft.transcoder.getVideoUrl(myAsset, {
110216
"width": 300,
111217
"height": 200,
112218
"timeInSecs": 20,
@@ -120,18 +226,173 @@ In the array you pass in, the default values are used if the key/value pair does
120226
"width" => 200,
121227
"height" => 100,
122228
"timeInSecs" => 10,
229+
"aspectRatio" => "letterbox",
230+
"sharpen" => true,
123231
}
124232

125233
If you want to have the Transcoder not change a parameter, pass in an empty value in the key/value pair, e.g.:
126234

127-
{% set transVideoThumbUrl = craft.transcoder.getVideoThumbnailUrl('/home/vagrant/sites/nystudio107/public/trimurti.mp4', {
235+
{% set transVideoThumbUrl = craft.transcoder.getVideoThumbnailUrl('/home/vagrant/sites/nystudio107/public/oceans.mp4', {
128236
"width": "",
129237
"height": "",
130238
"timeInSecs": 20,
131239
}) %}
132240

133241
The above example would cause it to generate a thumbnail at whatever size the video is (not recommended for client-proofing purposes).
134242

243+
The `aspectRatio` parameter lets you control how the video aspect ratio is maintained when it is scaled:
244+
245+
`none` results in the aspect ratio of the original video not being maintained, and the thumbnail image is scaled to the dimensions passed in:
246+
247+
![Screenshot](resources/screenshots/oceans_20s_300w_200h_none.jpg)
248+
249+
`crop` scales the video up to maintain the original aspect ratio, and then crops it so that the thumbnail image is full-frame:
250+
251+
![Screenshot](resources/screenshots/oceans_20s_300w_200h_crop.jpg)
252+
253+
`letterbox` scales the video to fit the new frame, putting a letterboxed or pillarboxed border to pad the thumbnail image:
254+
255+
![Screenshot](resources/screenshots/oceans_20s_300w_200h_letterbox.jpg)
256+
257+
You can control the color of the letterboxed area (it's `black` by default) via the `letterboxColor` option. It can be either a semantic color name, or a hexcode color, e.g.: `0xC0C0C0`
258+
259+
The `sharpen` option determines whether an unsharp mask filter should be applied to the scaled thumbnail image.
260+
261+
### Getting Information About a Video
262+
263+
To get information about an existing video, you can use `craft.transcoder.getFileInfo()`:
264+
265+
{% set transVideoUrl = craft.transcoder.getFileInfo('/home/vagrant/sites/nystudio107/public/oceans.mp4') %}
266+
267+
You can also pass in an `Asset`:
268+
269+
{% set myAsset = entry.someAsset.first() %}
270+
{% set transVideoUrl = craft.transcoder.getFileInfo(myAsset) %}
271+
272+
This returns an array with two top-level keys:
273+
274+
* `format` - information about the container file format
275+
* `streams` - information about each stream in the container; many videos have multiple streams, for instance, one for the video streams, and another for the audio stream. There can even be multiple video or audio streams in a container.
276+
277+
Here's example output from `craft.transcoder.getFileInfo`:
278+
279+
[
280+
'streams' => [
281+
0 => [
282+
'index' => 0
283+
'codec_name' => 'h264'
284+
'codec_long_name' => 'H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10'
285+
'profile' => 'Constrained Baseline'
286+
'codec_type' => 'video'
287+
'codec_time_base' => '1001/48000'
288+
'codec_tag_string' => 'avc1'
289+
'codec_tag' => '0x31637661'
290+
'width' => 960
291+
'height' => 400
292+
'coded_width' => 960
293+
'coded_height' => 400
294+
'has_b_frames' => 0
295+
'sample_aspect_ratio' => '1:1'
296+
'display_aspect_ratio' => '12:5'
297+
'pix_fmt' => 'yuv420p'
298+
'level' => 30
299+
'chroma_location' => 'left'
300+
'refs' => 3
301+
'is_avc' => '1'
302+
'nal_length_size' => '4'
303+
'r_frame_rate' => '24000/1001'
304+
'avg_frame_rate' => '24000/1001'
305+
'time_base' => '1/24000'
306+
'start_pts' => 0
307+
'start_time' => '0.000000'
308+
'duration_ts' => 1117116
309+
'duration' => '46.546500'
310+
'bit_rate' => '3859635'
311+
'bits_per_raw_sample' => '8'
312+
'nb_frames' => '1116'
313+
'disposition' => [
314+
'default' => 1
315+
'dub' => 0
316+
'original' => 0
317+
'comment' => 0
318+
'lyrics' => 0
319+
'karaoke' => 0
320+
'forced' => 0
321+
'hearing_impaired' => 0
322+
'visual_impaired' => 0
323+
'clean_effects' => 0
324+
'attached_pic' => 0
325+
]
326+
'tags' => [
327+
'creation_time' => '2013-05-03 22:50:47'
328+
'language' => 'und'
329+
'handler_name' => 'GPAC ISO Video Handler'
330+
]
331+
]
332+
1 => [
333+
'index' => 1
334+
'codec_name' => 'aac'
335+
'codec_long_name' => 'AAC (Advanced Audio Coding)'
336+
'profile' => 'LC'
337+
'codec_type' => 'audio'
338+
'codec_time_base' => '1/48000'
339+
'codec_tag_string' => 'mp4a'
340+
'codec_tag' => '0x6134706d'
341+
'sample_fmt' => 'fltp'
342+
'sample_rate' => '48000'
343+
'channels' => 2
344+
'channel_layout' => 'stereo'
345+
'bits_per_sample' => 0
346+
'r_frame_rate' => '0/0'
347+
'avg_frame_rate' => '0/0'
348+
'time_base' => '1/48000'
349+
'start_pts' => 0
350+
'start_time' => '0.000000'
351+
'duration_ts' => 2237440
352+
'duration' => '46.613333'
353+
'bit_rate' => '92926'
354+
'max_bit_rate' => '104944'
355+
'nb_frames' => '2185'
356+
'disposition' => [
357+
'default' => 1
358+
'dub' => 0
359+
'original' => 0
360+
'comment' => 0
361+
'lyrics' => 0
362+
'karaoke' => 0
363+
'forced' => 0
364+
'hearing_impaired' => 0
365+
'visual_impaired' => 0
366+
'clean_effects' => 0
367+
'attached_pic' => 0
368+
]
369+
'tags' => [
370+
'creation_time' => '2013-05-03 22:51:07'
371+
'language' => 'und'
372+
'handler_name' => 'GPAC ISO Audio Handler'
373+
]
374+
]
375+
]
376+
'format' => [
377+
'filename' => '/htdocs/craft3/public/assets/oceans.mp4'
378+
'nb_streams' => 2
379+
'nb_programs' => 0
380+
'format_name' => 'mov,mp4,m4a,3gp,3g2,mj2'
381+
'format_long_name' => 'QuickTime / MOV'
382+
'start_time' => '0.000000'
383+
'duration' => '46.613333'
384+
'size' => '23014356'
385+
'bit_rate' => '3949832'
386+
'probe_score' => 100
387+
'tags' => [
388+
'major_brand' => 'isom'
389+
'minor_version' => '1'
390+
'compatible_brands' => 'isomavc1'
391+
'creation_time' => '2013-05-03 22:51:07'
392+
]
393+
]
394+
]
395+
135396
### Generating a Download URL
136397

137398
To generate a download URL for a file, do the following:
@@ -147,7 +408,5 @@ The file must reside in the webroot (thus a URL or URI must be passed in as a pa
147408
Some things to do, and ideas for potential features:
148409

149410
* The videos could potentially be saved in different formats (though `.mp4` really is "the" standard for video)
150-
* The videos could potentially be resized, either to an aspect ratio or an absolute size or what have you
151-
* Accessors could be written to get information about a video (height, width, duration, and so on)
152411

153412
Brought to you by [nystudio107](https://nystudio107.com)

0 commit comments

Comments
 (0)