@@ -28,22 +28,27 @@ Transcoder.into(filePath)
28
28
29
29
Take a look at the demo app for a real example or keep reading below for documentation.
30
30
31
- * Note: this project is an improved fork of [ ypresto/android-transcoder] ( https://github.com/ypresto/android-transcoder ) .
32
- It features a lot of improvements over the original project, including:*
33
-
34
- - * Multithreading support*
35
- - * Crop to any aspect ratio*
36
- - * Set output video rotation*
37
- - * Various bugs fixed*
38
- - * [ Input] ( #data-sources ) : Accept content Uris and other types*
39
- - * [ Real error handling] ( #listening-for-events ) instead of errors being thrown*
40
- - * Frame dropping support, which means you can set the video frame rate*
41
- - * Source project is over-conservative when choosing options that * might* not be supported. We prefer to try and let the codec fail*
42
- - * More convenient APIs for transcoding & choosing options*
43
- - * Configurable [ Validators] ( #validators ) to e.g. ** not** perform transcoding if the source video is already compressed enough*
44
- - * Expose internal logs through Logger (so they can be reported to e.g. Crashlytics)*
45
- - * Handy utilities for track configuration through [ Output Strategies] ( #output-strategies ) *
46
- - * Handy utilities for resizing*
31
+ ## Features
32
+
33
+ - Fast transcoding to AAC/AVC
34
+ - Hardware accelerated
35
+ - Multithreaded
36
+ - Convenient, fluent API
37
+ - Choose output size, with automatic cropping [[ docs]] ( #video-size )
38
+ - Choose output rotation [[ docs]] ( #video-rotation )
39
+ - Choose output speed [[ docs]] ( #video-speed )
40
+ - Choose output frame rate [[ docs]] ( #other-options )
41
+ - Choose output audio channels [[ docs]] ( #audio-strategies )
42
+ - Override frames timestamp, e.g. to slow down the middle part of the video [[ docs]] ( #time-interpolation )
43
+ - Error handling [[ docs]] ( #listening-for-events )
44
+ - Configurable validators to e.g. avoid transcoding if the source is already compressed enough [[ docs]] ( #validators )
45
+ - Configurable video and audio strategies [[ docs]] ( #output-strategies )
46
+
47
+ * This project started as a fork of [ ypresto/android-transcoder] ( https://github.com/ypresto/android-transcoder ) .
48
+ With respect to the source project, which misses most of the functionality listed above,
49
+ we have also fixed a huge number of bugs and are much less conservative when choosing options
50
+ that might not be supported. The source project will always throw - for example, accepting only 16:9,
51
+ AVC Baseline Profile videos - we prefer to try and let the codec fail if it wants to* .
47
52
48
53
## Setup
49
54
@@ -128,8 +133,8 @@ Transcoding operation did succeed. The success code can be:
128
133
129
134
| Code| Meaning|
130
135
| ----| -------|
131
- | ` MediaTranscoder .SUCCESS_TRANSCODED` | Transcoding was executed successfully. Transcoded file was written to the output path.|
132
- | ` MediaTranscoder .SUCCESS_NOT_NEEDED` | Transcoding was not executed because it was considered ** not needed** by the ` Validator ` .|
136
+ | ` Transcoder .SUCCESS_TRANSCODED` | Transcoding was executed successfully. Transcoded file was written to the output path.|
137
+ | ` Transcoder .SUCCESS_NOT_NEEDED` | Transcoding was not executed because it was considered ** not needed** by the ` Validator ` .|
133
138
134
139
Keep reading [ below] ( #validators ) to know about ` Validator ` s.
135
140
@@ -220,9 +225,9 @@ audio stream to AAC format with the specified number of channels.
220
225
221
226
``` java
222
227
Transcoder . into(filePath)
223
- .setAudioOutputStrategy(DefaultAudioStrategy(1 )) // or..
224
- .setAudioOutputStrategy(DefaultAudioStrategy(2 )) // or..
225
- .setAudioOutputStrategy(DefaultAudioStrategy(DefaultAudioStrategy . AUDIO_CHANNELS_AS_IS ))
228
+ .setAudioOutputStrategy(new DefaultAudioStrategy (1 )) // or..
229
+ .setAudioOutputStrategy(new DefaultAudioStrategy (2 )) // or..
230
+ .setAudioOutputStrategy(new DefaultAudioStrategy (DefaultAudioStrategy . AUDIO_CHANNELS_AS_IS ))
226
231
// ...
227
232
```
228
233
@@ -243,16 +248,16 @@ We provide helpers for common tasks:
243
248
DefaultVideoStrategy strategy;
244
249
245
250
// Sets an exact size. If aspect ratio does not match, cropping will take place.
246
- strategy = DefaultVideoStrategy . exact(1080 , 720 ). build()
251
+ strategy = DefaultVideoStrategy . exact(1080 , 720 ). build();
247
252
248
253
// Keeps the aspect ratio, but scales down the input size with the given fraction.
249
- strategy = DefaultVideoStrategy . fraction(0.5F ). build()
254
+ strategy = DefaultVideoStrategy . fraction(0.5F ). build();
250
255
251
256
// Ensures that each video size is at most the given value - scales down otherwise.
252
- strategy = DefaultVideoStrategy . atMost(1000 ). build()
257
+ strategy = DefaultVideoStrategy . atMost(1000 ). build();
253
258
254
259
// Ensures that minor and major dimension are at most the given values - scales down otherwise.
255
- strategy = DefaultVideoStrategy . atMost(500 , 1000 ). build()
260
+ strategy = DefaultVideoStrategy . atMost(500 , 1000 ). build();
256
261
```
257
262
258
263
In fact, all of these will simply call ` new DefaultVideoStrategy.Builder(resizer) ` with a special
@@ -270,14 +275,14 @@ You can also group resizers through `MultiResizer`, which applies resizers in ch
270
275
271
276
``` java
272
277
// First scales down, then ensures size is at most 1000. Order matters!
273
- Resizer resizer = new MultiResizer ()
274
- resizer. addResizer(new FractionResizer (0.5F ))
275
- resizer. addResizer(new AtMostResizer (1000 ))
278
+ Resizer resizer = new MultiResizer ();
279
+ resizer. addResizer(new FractionResizer (0.5F ));
280
+ resizer. addResizer(new AtMostResizer (1000 ));
276
281
277
282
// First makes it 16:9, then ensures size is at most 1000. Order matters!
278
- Resizer resizer = new MultiResizer ()
279
- resizer. addResizer(new AspectRatioResizer (16F / 9F ))
280
- resizer. addResizer(new AtMostResizer (1000 ))
283
+ Resizer resizer = new MultiResizer ();
284
+ resizer. addResizer(new AspectRatioResizer (16F / 9F ));
285
+ resizer. addResizer(new AtMostResizer (1000 ));
281
286
```
282
287
283
288
This option is already available through the DefaultVideoStrategy builder, so you can do:
@@ -287,7 +292,7 @@ DefaultVideoStrategy strategy = new DefaultVideoStrategy.Builder()
287
292
.addResizer(new AspectRatioResizer (16F / 9F ))
288
293
.addResizer(new FractionResizer (0.5F ))
289
294
.addResizer(new AtMostResizer (1000 ))
290
- .build()
295
+ .build();
291
296
```
292
297
293
298
### Other options
@@ -300,10 +305,10 @@ DefaultVideoStrategy strategy = new DefaultVideoStrategy.Builder()
300
305
.bitRate(DefaultVideoStrategy . BITRATE_UNKNOWN ) // tries to estimate
301
306
.frameRate(frameRate) // will be capped to the input frameRate
302
307
.iFrameInterval(interval) // interval between I-frames in seconds
303
- .build()
308
+ .build();
304
309
```
305
310
306
- ## Other Options
311
+ ## Advanced Options
307
312
308
313
#### Video rotation
309
314
@@ -316,14 +321,78 @@ Transcoder.into(filePath)
316
321
// ...
317
322
```
318
323
324
+ #### Time interpolation
325
+
326
+ We offer APIs to change the timestamp of each video and audio frame. You can pass a ` TimeInterpolator `
327
+ to the transcoder builder to be able to receive the frame timestamp as input, and return a new one
328
+ as output.
329
+
330
+ ``` java
331
+ Transcoder . into(filePath)
332
+ .setTimeInterpolator(timeInterpolator)
333
+ // ...
334
+ ```
335
+
336
+ As an example, this is the implementation of the default interpolator, called ` DefaultTimeInterpolator ` ,
337
+ that will just return the input time unchanged:
338
+
339
+ ``` java
340
+ @Override
341
+ public long interpolate(@NonNull TrackType type, long time) {
342
+ // Receive input time in microseconds and return a possibly different one.
343
+ return time;
344
+ }
345
+ ```
346
+
347
+ It should be obvious that returning invalid times can make the process crash at any point, or at least
348
+ the transcoding operation fail.
349
+
350
+ #### Video speed
351
+
352
+ We also offer a special time interpolator called ` SpeedTimeInterpolator ` that accepts a ` float ` parameter
353
+ and will modify the video speed.
354
+
355
+ - A speed factor equal to 1 will leave speed unchanged
356
+ - A speed factor < 1 will slow the video down
357
+ - A speed factor > 1 will accelerate the video
358
+
359
+ This interpolator can be set using ` setTimeInterpolator(TimeInterpolator) ` , or, as a shorthand,
360
+ using ` setSpeed(float) ` :
361
+
362
+ ``` java
363
+ Transcoder . into(filePath)
364
+ .setSpeed(0.5F ) // 0.5x
365
+ .setSpeed(1F ) // Unchanged
366
+ .setSpeed(2F ) // Twice as fast
367
+ // ...
368
+ ```
369
+
370
+ #### Audio stretching
371
+
372
+ When a time interpolator alters the frames and samples timestamps, you can either remove audio or
373
+ stretch the audio samples to the new length. This is done through the ` AudioStretcher ` interface:
374
+
375
+ ``` java
376
+ Transcoder . into(filePath)
377
+ .setAudioStretcher(audioStretcher)
378
+ // ...
379
+ ```
380
+
381
+ The default audio stretcher, ` DefaultAudioStretcher ` , will:
382
+
383
+ - When we need to shrink a group of samples, cut the last ones
384
+ - When we need to stretch a group of samples, insert noise samples in between
385
+
386
+ Please take a look at the implementation and read class documentation.
387
+
319
388
## Compatibility
320
389
321
390
As stated pretty much everywhere, ** not all codecs/devices/manufacturers support all sizes/options** .
322
391
This is a complex issue which is especially important for video strategies, as a wrong size can lead
323
392
to a transcoding error or corrupted file.
324
393
325
394
Android platform specifies requirements for manufacturers through the [ CTS (Compatibility test suite)] ( https://source.android.com/compatibility/cts ) .
326
- Only a few codecs and sizes are strictly required to work.
395
+ Only a few codecs and sizes are ** strictly** required to work.
327
396
328
397
We collect common presets in the ` DefaultVideoStrategies ` class:
329
398
0 commit comments