11package VideoHandle ;
22
33import android .app .Activity ;
4+ import android .app .Application ;
45import android .content .Context ;
56import android .media .MediaExtractor ;
67import android .media .MediaFormat ;
@@ -25,14 +26,15 @@ public class EpEditor {
2526private static final int DEFAULT_WIDTH = 480 ;//默认输出宽度
2627private static final int DEFAULT_HEIGHT = 360 ;//默认输出高度
2728
28- private Context context ;
29-
3029public enum Format {
3130MP3 , MP4
3231}
3332
34- public EpEditor (Context context ) {
35- this .context = context ;
33+ public enum PTS {
34+ VIDEO , AUDIO , ALL
35+ }
36+
37+ private EpEditor () {
3638}
3739
3840/**
@@ -41,7 +43,7 @@ public EpEditor(Context context) {
4143 * @param epVideo 需要处理的视频
4244 * @param outputOption 输出选项配置
4345 */
44- public void exec (EpVideo epVideo , OutputOption outputOption , OnEditorListener onEditorListener ) {
46+ public static void exec (EpVideo epVideo , OutputOption outputOption , OnEditorListener onEditorListener ) {
4547boolean isFilter = false ;
4648ArrayList <EpDraw > epDraws = epVideo .getEpDraws ();
4749//开始处理
@@ -107,7 +109,7 @@ public void exec(EpVideo epVideo, OutputOption outputOption, OnEditorListener on
107109isFilter = true ;
108110}
109111}
110- if (!filter_complex .toString ().equals ("" )) {
112+ if (!filter_complex .toString ().equals ("" )) {
111113cmd .append (filter_complex .toString ());
112114}
113115}
@@ -139,7 +141,7 @@ public void exec(EpVideo epVideo, OutputOption outputOption, OnEditorListener on
139141 * @param epVideos 需要合并的视频集合
140142 * @param outputOption 输出选项配置
141143 */
142- public void merge (List <EpVideo > epVideos , OutputOption outputOption , OnEditorListener onEditorListener ) {
144+ public static void merge (List <EpVideo > epVideos , OutputOption outputOption , OnEditorListener onEditorListener ) {
143145//检测是否有无音轨视频
144146boolean isNoAudioTrack = false ;
145147for (EpVideo epVideo : epVideos ) {
@@ -225,7 +227,7 @@ public void merge(List<EpVideo> epVideos, OutputOption outputOption, OnEditorLis
225227}
226228filter_complex .append ("concat=n=" ).append (epVideos .size ()).append (":v=0:a=1[outa]" );
227229}
228- if (!filter_complex .toString ().equals ("" )) {
230+ if (!filter_complex .toString ().equals ("" )) {
229231cmd .append (filter_complex .toString ());
230232}
231233cmd .append ("-map" ).append ("[outv]" );
@@ -259,11 +261,12 @@ public void merge(List<EpVideo> epVideos, OutputOption outputOption, OnEditorLis
259261 * <p>
260262 * 注意:此方法要求视频格式非常严格,需要合并的视频必须分辨率相同,帧率和码率也得相同
261263 *
264+ * @param context Context
262265 * @param epVideos 需要合并的视频的集合
263266 * @param outputOption 输出选项
264267 * @param onEditorListener 回调监听
265268 */
266- public void mergeByLc (List <EpVideo > epVideos , OutputOption outputOption , final OnEditorListener onEditorListener ) {
269+ public static void mergeByLc (Context context , List <EpVideo > epVideos , OutputOption outputOption , final OnEditorListener onEditorListener ) {
267270String appDir = context .getFilesDir ().getAbsolutePath () + "/EpVideos/" ;
268271String fileName = "ffmpeg_concat.txt" ;
269272List <String > videos = new ArrayList <>();
@@ -297,7 +300,7 @@ public void mergeByLc(List<EpVideo> epVideos, OutputOption outputOption, final O
297300 * @param audioVolume 背景音乐音量(例:1.5为150%)
298301 * @param onEditorListener 回调监听
299302 */
300- public void music (String videoin , String audioin , String output , float videoVolume , float audioVolume , OnEditorListener onEditorListener ) {
303+ public static void music (String videoin , String audioin , String output , float videoVolume , float audioVolume , OnEditorListener onEditorListener ) {
301304MediaExtractor mediaExtractor = new MediaExtractor ();
302305try {
303306mediaExtractor .setDataSource (videoin );
@@ -331,7 +334,7 @@ public void music(String videoin, String audioin, String output, float videoVolu
331334 * @param format 输出类型
332335 * @param onEditorListener 回调监听
333336 */
334- public void demuxer (String videoin , String out , Format format , OnEditorListener onEditorListener ) {
337+ public static void demuxer (String videoin , String out , Format format , OnEditorListener onEditorListener ) {
335338CmdList cmd = new CmdList ();
336339cmd .append ("ffmpeg" ).append ("-y" ).append ("-i" ).append (videoin );
337340switch (format ) {
@@ -346,6 +349,50 @@ public void demuxer(String videoin, String out, Format format, OnEditorListener
346349execCmd (cmd , 0 , onEditorListener );
347350}
348351
352+ /**
353+ * 音视频变速
354+ *
355+ * @param videoin 音视频文件
356+ * @param out 输出路径
357+ * @param times 倍率(调整范围0.25-4)
358+ * @param pts 加速类型
359+ * @param onEditorListener 回调接口
360+ */
361+ public static void changePTS (String videoin , String out , float times , PTS pts , OnEditorListener onEditorListener ) {
362+ if (times < 0.25f || times > 4.0f ) {
363+ Log .e ("ffmpeg" , "times参数错误,播放速率调整范围0.25-4倍" );
364+ onEditorListener .onFailure ();
365+ return ;
366+ }
367+ CmdList cmd = new CmdList ();
368+ cmd .append ("ffmpeg" ).append ("-y" ).append ("-i" ).append (videoin );
369+ String t = "atempo=" + times ;
370+ if (times < 0.5f ) {
371+ t = "atempo=0.5,atempo=" + (times / 0.5f );
372+ } else if (times > 2.0f ) {
373+ t = "atempo=2.0,atempo=" + (times / 2.0f );
374+ }
375+ Log .v ("ffmpeg" , "atempo:" + t );
376+ switch (pts ) {
377+ case VIDEO :
378+ cmd .append ("-filter_complex" ).append ("[0:v]setpts=" + (1 / times ) + "*PTS" ).append ("-an" );
379+ break ;
380+ case AUDIO :
381+ cmd .append ("-filter:a" ).append (t );
382+ break ;
383+ case ALL :
384+ cmd .append ("-filter_complex" ).append ("[0:v]setpts=" + (1 / times ) + "*PTS[v];[0:a]" + t + "[a]" )
385+ .append ("-map" ).append ("[v]" ).append ("-map" ).append ("[a]" );
386+ break ;
387+ }
388+ cmd .append ("-preset" ).append ("superfast" ).append (out );
389+ long d = VideoUitls .getDuration (videoin );
390+ double dd = d / times ;
391+ long ddd = (long ) dd ;
392+ Log .v ("ffmpeg" , "JD:" + d + "," + dd + "," + ddd );
393+ execCmd (cmd , ddd , onEditorListener );
394+ }
395+
349396
350397/**
351398 * 输出选项设置
@@ -448,38 +495,23 @@ public void setHeight(int height) {
448495 *
449496 * @param cmd 命令
450497 */
451- public void execCmd (String cmd , long duration , final OnEditorListener onEditorListener ) {
498+ public static void execCmd (String cmd , long duration , final OnEditorListener onEditorListener ) {
452499cmd = "ffmpeg " + cmd ;
453500String [] cmds = cmd .split (" " );
454501FFmpegCmd .exec (cmds , duration , new OnEditorListener () {
455502@ Override
456503public void onSuccess () {
457- ((Activity ) context ).runOnUiThread (new Runnable () {
458- @ Override
459- public void run () {
460- onEditorListener .onSuccess ();
461- }
462- });
504+ onEditorListener .onSuccess ();
463505}
464506
465507@ Override
466508public void onFailure () {
467- ((Activity ) context ).runOnUiThread (new Runnable () {
468- @ Override
469- public void run () {
470- onEditorListener .onFailure ();
471- }
472- });
509+ onEditorListener .onFailure ();
473510}
474511
475512@ Override
476513public void onProgress (final float progress ) {
477- ((Activity ) context ).runOnUiThread (new Runnable () {
478- @ Override
479- public void run () {
480- onEditorListener .onProgress (progress );
481- }
482- });
514+ onEditorListener .onProgress (progress );
483515}
484516});
485517}
@@ -489,40 +521,25 @@ public void run() {
489521 *
490522 * @param cmd 命令
491523 */
492- public void execCmd (CmdList cmd , long duration , final OnEditorListener onEditorListener ) {
524+ private static void execCmd (CmdList cmd , long duration , final OnEditorListener onEditorListener ) {
493525String [] cmds = cmd .toArray (new String [cmd .size ()]);
494- for (String ss : cmds ) {
495- Log .v ("EpMediaF" ,"cmd:" + ss );
526+ for (String ss : cmds ) {
527+ Log .v ("EpMediaF" , "cmd:" + ss );
496528}
497529FFmpegCmd .exec (cmds , duration , new OnEditorListener () {
498530@ Override
499531public void onSuccess () {
500- ((Activity ) context ).runOnUiThread (new Runnable () {
501- @ Override
502- public void run () {
503- onEditorListener .onSuccess ();
504- }
505- });
532+ onEditorListener .onSuccess ();
506533}
507534
508535@ Override
509536public void onFailure () {
510- ((Activity ) context ).runOnUiThread (new Runnable () {
511- @ Override
512- public void run () {
513- onEditorListener .onFailure ();
514- }
515- });
537+ onEditorListener .onFailure ();
516538}
517539
518540@ Override
519541public void onProgress (final float progress ) {
520- ((Activity ) context ).runOnUiThread (new Runnable () {
521- @ Override
522- public void run () {
523- onEditorListener .onProgress (progress );
524- }
525- });
542+ onEditorListener .onProgress (progress );
526543}
527544});
528545}
0 commit comments