FFmpeg บน Android


207

ฉันได้รวบรวม FFmpeg (libffmpeg.so) บน Android แล้ว ตอนนี้ฉันต้องสร้างแอปพลิเคชันอย่าง RockPlayer หรือใช้กรอบมัลติมีเดีย Android ที่มีอยู่เพื่อเรียก FFmpeg

  1. คุณมีขั้นตอน / ขั้นตอน / รหัส / ตัวอย่างในการรวม FFmpeg บน Android / StageFright หรือไม่?

  2. คุณช่วยแนะนำฉันเกี่ยวกับวิธีใช้ไลบรารีนี้สำหรับการเล่นมัลติมีเดียได้อย่างไร

  3. ฉันมีข้อกำหนดที่ฉันมีการส่งผ่านข้อมูลเสียงและวิดีโอซึ่งฉันต้องการฟีดไปที่ FFmpeg และถอดรหัส / เรนเดอร์ ฉันจะทำสิ่งนี้บน Android ได้อย่างไรเนื่องจาก IOMX APIs นั้นใช้ OMX และไม่สามารถปลั๊กอิน FFmpeg ได้ที่นี่

  4. ฉันไม่สามารถหาเอกสารเกี่ยวกับ FFmpeg API ที่ต้องใช้สำหรับการเล่น


7
นี่เป็นเรื่องที่น่าสนใจฉันก็อยากรู้อยากเห็นด้วย
Axarydax

5
คุณรวบรวม ffmpeg เพื่อรับไฟล์. so อย่างไร คุณช่วยแบ่งปันขั้นตอนที่คุณติดตามได้ไหม ฉันกำลังทำงานบน windows กับ cygwin-1.7.9 และ ndk r5 โปรดช่วยฉันด้วย
Swathi EP

นี่คือ FFmpeg ที่ค่อนข้างใหม่สำหรับ Android: sourceforge.net/projects/ffmpeg4android
slhck

@slhck ฉันได้ดาวน์โหลดรหัส ffmpeg จากลิงค์ด้านบนและพยายามรวบรวมมัน แต่ฉันไม่สามารถรับไฟล์. so มันแสดงให้เห็นปัญหามาก ..
RAJESH

โปรดช่วยฉันด้วย: stackoverflow.com/questions/14157030/ …ฉันไม่ทราบว่าจะรวมฟังก์ชั่นนี้และใช้งาน
ที่ไหน

คำตอบ:


109

นี่คือขั้นตอนที่ฉันได้ทำเพื่อให้ ffmpeg ทำงานบน Android:

  1. สร้างห้องสมุดคงที่ของ ffmpeg สำหรับ Android นี่คือความสำเร็จโดยการสร้างหุ่นยนต์พอร์ต ffmpeg olvaffe ของ ( libffmpeg ) โดยใช้รูปร่าง Android ระบบ เพียงวางแหล่งที่มาภายใต้ / ภายนอกและmakeออกไป คุณจะต้องแยกไบโอนิค (libc) และ zlib (libz) ออกจากบิลด์ Android เช่นกันเนื่องจากไลบรารี ffmpeg ขึ้นอยู่กับพวกเขา
  2. สร้างการทำงานแบบไดนามิกห้องสมุดตัด ffmpeg ที่ใช้ Android NDK มีเอกสารจำนวนมากเกี่ยวกับวิธีการทำงานกับ NDK โดยทั่วไปคุณจะต้องเขียนโค้ด C / C ++ บางส่วนเพื่อส่งออกฟังก์ชันที่คุณต้องการจาก ffmpeg ไปยังไลบรารี java สามารถโต้ตอบกับผ่าน JNI NDK ช่วยให้คุณเชื่อมโยงกับไลบรารีแบบคงที่ที่คุณสร้างในขั้นตอนที่ 1 ได้อย่างง่ายดายเพียงเพิ่มบรรทัดที่คล้ายกับ Android.mk นี้:LOCAL_STATIC_LIBRARIES := libavcodec libavformat libavutil libc libz

  3. ใช้ไลบรารีแบบไดนามิกการห่อ ffmpeg จากแหล่ง java ของคุณ มีเอกสารเกี่ยวกับ JNI เพียงพอคุณควรจะปรับ

เกี่ยวกับการใช้ ffmpeg สำหรับการเล่นมีหลายตัวอย่าง (ไบนารี ffmpeg นั้นเป็นตัวอย่างที่ดี) นี่คือการสอนพื้นฐาน เอกสารที่ดีที่สุดสามารถพบได้ในส่วนหัว

โชคดี :)


7
มีลิงก์ไม่กี่คำตอบสำหรับการสร้าง ffmpeg สำหรับ Android นี่ยังเป็นทางออกที่ดีที่สุดหรือไม่? ลิงก์ Android Build System ใช้งานไม่ได้ - สิ่งที่ควรจะเป็น? มีชุดเครื่องมือมากมายที่จะช่วยในการสร้างด้วย NDK อย่างไรก็ตามพวกเขาทั้งหมดล้มเหลวด้วยข้อผิดพลาดในการสร้างต่าง ๆ สำหรับฉันและดูเก่าไปหน่อย มีเหตุผลใดที่คนไม่สามารถโพสต์ lib ffmpeg แบบคงที่ได้หรือไม่?
Rob Lourens

7
เพื่อตอบคำถามของฉันฉันพบว่า repo นี้มีประโยชน์มากที่สุดสำหรับการสร้าง ffmpeg และ JNI wrappers - github.com/andynicholson/android-ffmpeg-x264
Rob Lourens

68

ด้วยเหตุผลต่าง ๆ มัลติมีเดียเป็นและไม่เคยง่ายในแง่ของการบรรลุภารกิจโดยไม่ลดทอนประสิทธิภาพ ffmpeg เป็นความพยายามในการปรับปรุงทุกวัน สนับสนุนรูปแบบที่แตกต่างกันของตัวแปลงสัญญาณและคอนเทนเนอร์

ตอนนี้เพื่อตอบคำถามวิธีการใช้ไลบรารีนี้ฉันจะบอกว่ามันไม่ง่ายเลยที่จะเขียนที่นี่ แต่ผมสามารถแนะนำคุณในวิธีต่อไปนี้

1) ภายในไดเรกทอรี ffmpeg ของรหัสที่มาคุณต้องoutput_example.cหรือapi_example.c ที่นี่คุณสามารถดูรหัสที่จะทำการเข้ารหัส / ถอดรหัส คุณจะได้รับแนวคิดว่า API ภายในใดที่คุณควรโทรหา ffmpeg นี่จะเป็นขั้นตอนแรกของคุณ

2) Dolphin player เป็นโครงการโอเพ่นซอร์สสำหรับ Android ขณะนี้มีข้อบกพร่อง แต่นักพัฒนาทำงานอย่างต่อเนื่อง ในโครงการนั้นคุณมีการตั้งค่าทั้งหมดซึ่งคุณสามารถใช้เพื่อดำเนินการสอบสวนต่อ นี่คือลิงค์ไปยังโครงการจาก code.google.com หรือเรียกใช้คำสั่ง " git clone https://code.google.com/p/dolphin-player/ " ในเทอร์มินัล คุณสามารถเห็นสองโครงการชื่อ P และ P86 คุณสามารถใช้อย่างใดอย่างหนึ่ง

เคล็ดลับพิเศษที่ฉันต้องการนำเสนอคือเมื่อคุณสร้างรหัส ffmpeg ภายใน build.sh คุณจะต้องเปิดใช้งาน muxers / demuxers / encoders / decoders ของรูปแบบที่คุณต้องการใช้ มิฉะนั้นรหัสที่เกี่ยวข้องจะไม่รวมอยู่ในไลบรารี ฉันใช้เวลานานมากในการตระหนักถึงสิ่งนี้ คิดว่าจะแบ่งปันกับคุณ

พื้นฐานไม่กี่: เมื่อเราพูดไฟล์วิดีโอเช่น: avi มันเป็นการรวมกันของทั้งเสียงและวิดีโอ

ไฟล์วิดีโอ = วิดีโอ + เสียง


วิดีโอ = Codec + Muxer + Demuxer

codec = encoder + Decoder

=> Video = ตัวเข้ารหัส + ตัวถอดรหัส + Muxer + Demuxer (Mpeg4 + Mpeg4 + avi + avi - ตัวอย่างสำหรับคอนเทนเนอร์ avi)


Audio = Codec + Muxer + Demuxer

codec = encoder + Decoder

=> Audio = ตัวเข้ารหัส + ตัวถอดรหัส + Muxer + Demuxer (mp2 + mp2 + avi + avi - ตัวอย่างสำหรับคอนเทนเนอร์ avi)


Codec (ชื่อคือ deriverd จากการรวมกันของ en * co * der / * dec * oder) เป็นเพียงส่วนหนึ่งของรูปแบบที่กำหนดอัลกอริทึมที่ใช้ในการเข้ารหัส / ถอดรหัสเฟรม AVI ไม่ใช่ตัวแปลงสัญญาณมันเป็นคอนเทนเนอร์ที่ใช้ตัวแปลงสัญญาณวิดีโอของ Mpeg4 และตัวแปลงสัญญาณเสียงของ mp2

Muxer / demuxer ใช้เพื่อรวม / แยกเฟรมออกจากไฟล์ที่ใช้ขณะเข้ารหัส / ถอดรหัส

ดังนั้นหากคุณต้องการใช้รูปแบบ avi คุณต้องเปิดใช้งานคอมโพเนนต์วิดีโอ + คอมโพเนนต์เสียง

ตัวอย่างเช่นสำหรับ avi คุณต้องเปิดใช้งานสิ่งต่อไปนี้ ตัวเข้ารหัส mpeg4, ตัวถอดรหัส mpeg4, ตัวเข้ารหัส mp2, ตัวถอดรหัส mp2, avi muxer, avi demuxer

phewwwwwww ...

โดยทางโปรแกรม build.sh ควรมีรหัสต่อไปนี้:

--enable-muxer=avi --enable-demuxer=avi (Generic for both audio/video. generally Specific to a container)
--enable-encoder=mpeg4 --enable-decoder=mpeg4(For video support)
--enable-encoder=mp2 --enable-decoder=mp2 (For Audio support)

หวังว่าฉันจะไม่สับสนคุณมากขึ้นหลังจากนี้ ...

ขอบคุณความช่วยเหลือใด ๆ ที่จำเป็นโปรดแจ้งให้เราทราบ


1
เฮ้ฉันอยากจะขอบคุณมากสำหรับข้อมูลนั้นคุณช่วยฉันได้มากจริงๆเป็นไปได้ไหมที่คุณจะช่วยฉันถ้าฉันต้องการในภายหลัง ขอบคุณ!
idish

ฉันสามารถเพิ่มคุณด้วย Skype หรือ MSN หรือแพลตฟอร์มแชทอื่น ๆ ได้ไหม ฉันมีคำถามสองสามข้อเกี่ยวกับเรื่องนี้ขอบคุณ
idish

2
แน่นอนว่า .. !! แต่สถานะออนไลน์ของฉันค่อนข้างต่ำ .. เว้นแต่เป็นสิ่งจำเป็นอย่างยิ่งฉันไม่ได้ลงชื่อเข้าใช้ Skype คุณสามารถส่งจดหมายถึงฉันสำหรับสิ่งสำคัญใด ๆ อีเมล: mantykuma@gmail.com
mk ..

13

การใช้งานที่ง่ายที่สุดในการสร้างและใช้งานง่ายที่ฉันพบได้ทำโดยทีม theguardianproject: https://github.com/guardianproject/android-ffmpeg


ไม่แน่ใจฉันเดาว่ามันไม่มีอะไรใน iOS เวอร์ชันใหม่ที่มาพร้อมกับความคิดที่อาจผิดพลาด เมื่อฉันโพสต์สิ่งนี้ฉันยังมี 10.7 หรือ 10.6
Guy

คุณรู้หรือไม่ว่าฉันจะแปลง 3gp เป็น audio ได้อย่างไรโดยใช้การใช้งาน JNI
Mr.G

11

ฉันได้ทำโปรเจคเล็ก ๆ น้อย ๆ เพื่อกำหนดค่าและสร้าง X264 และ FFMPEG โดยใช้ Android NDK สิ่งสำคัญที่ขาดหายไปคืออินเตอร์เฟส JNI ที่ดีเพื่อให้สามารถเข้าถึงได้ผ่าน Java แต่นั่นเป็นส่วนที่ง่าย (ค่อนข้าง) เมื่อฉันได้รับรอบในการทำให้ส่วนต่อประสาน JNI ดีสำหรับการใช้งานของฉันเองฉันจะผลักดันสิ่งนั้น

ข้อดีของระบบสร้าง olvaffe คือไม่ต้องใช้ไฟล์ Android.mk ในการสร้างไลบรารี่เพียงใช้ไฟล์ makefiles และ toolchain ทั่วไป สิ่งนี้ทำให้มีโอกาสน้อยที่จะหยุดทำงานเมื่อคุณดึงการเปลี่ยนแปลงใหม่จาก FFMPEG หรือ X264

https://github.com/halfninja/android-ffmpeg-x264


นิคโครงการของคุณไม่ได้รวบรวมบน OS X 10.7 libx264.a (common.o): ในฟังก์ชั่นx264_param_parse': common.c:(.text+0x2864): undefined reference to _DefaultRuneLocale 'collect2: ld ส่งคืนสถานะทางออก 1 รายการ: *** [x264] ข้อผิดพลาด 1
Yuriy Solovyov

9

หลังจากการวิจัยมากมายตอนนี้นี่เป็นห้องสมุดรวบรวมที่อัปเดตมากที่สุดสำหรับ Android ที่ฉันพบ:

https://github.com/bravobit/FFmpeg-Android

  • ในขณะนี้กำลังใช้ FFmpeg release n4.0-39-gda39990
  • รวม FFmpeg และ FFProbe
  • มีอินเตอร์เฟส Java เพื่อเรียกใช้คำสั่ง
  • FFprobe หรือ FFmpeg สามารถลบออกจาก APK ตรวจสอบวิกิได้ที่https://github.com/bravobit/FFmpeg-Android/wiki

6

ในการสร้างแอปพลิเคชัน FFMPEG ของฉันฉันใช้โครงการนี้ ( https://github.com/hiteshsondhi88/ffmpeg-android-java ) ดังนั้นฉันจึงไม่ต้องรวบรวมอะไรเลย ฉันคิดว่ามันเป็นวิธีที่ง่ายในการใช้ FFMPEG ในแอปพลิเคชัน Android ของเรา

ข้อมูลเพิ่มเติมเกี่ยวกับhttp://hiteshsondhi88.github.io/ffmpeg-android-java/


3
เสื้อคลุมนี้ช้ามาก ๆ มาก ๆ 200 ภาพไปยังวิดีโอใช้เวลา 50-60 วินาที . . แต่โดยปกติ ffmpeg จะจัดการงานนั้นใน 4-5 วินาที
Arsen Sench

โครงการนี้ไม่ทำงานอีกต่อไป คุณมีทรัพยากรอื่น ๆ บ้างไหม?
Ajeet

@ ArsenSench คุณมีวิธีแก้ปัญหาอื่น ๆ ?
Akash Dubey

3

แรงบันดาลใจจาก FFmpeg อื่น ๆ อีกมากมายในการใช้งาน Android ออกมี (ส่วนใหญ่โครงการguadian ) ฉันพบวิธีแก้ปัญหา (ด้วยการสนับสนุน Lame ด้วย)

(lame และ FFmpeg: https://github.com/intervigilium/liblameและhttp://bambuser.com/opensource )

โทร FFmpeg:

new Thread(new Runnable() {

    @Override
    public void run() {

        Looper.prepare();

        FfmpegController ffmpeg = null;

        try {
            ffmpeg = new FfmpegController(context);
        } catch (IOException ioe) {
            Log.e(DEBUG_TAG, "Error loading ffmpeg. " + ioe.getMessage());
        }

        ShellDummy shell = new ShellDummy();
        String mp3BitRate = "192";

        try {
            ffmpeg.extractAudio(in, out, audio, mp3BitRate, shell);
        } catch (IOException e) {
            Log.e(DEBUG_TAG, "IOException running ffmpeg" + e.getMessage());
        } catch (InterruptedException e) {
            Log.e(DEBUG_TAG, "InterruptedException running ffmpeg" + e.getMessage());
        }

        Looper.loop();

    }

}).start();

และเพื่อจัดการเอาต์พุตคอนโซล:

private class ShellDummy implements ShellCallback {

    @Override
    public void shellOut(String shellLine) {
        if (someCondition) {
            doSomething(shellLine);
        }
        Utils.logger("d", shellLine, DEBUG_TAG);
    }

    @Override
    public void processComplete(int exitValue) {
        if (exitValue == 0) {
            // Audio job OK, do your stuff: 

                            // i.e.             
                            // write id3 tags,
                            // calls the media scanner,
                            // etc.
        }
    }

    @Override
    public void processNotStartedCheck(boolean started) {
        if (!started) {
                            // Audio job error, as above.
        }
    }
}

คุณมีประสบการณ์อย่างไรกับโครงการผู้ปกครอง?
XY

3

แปลกที่โครงการนี้ไม่ได้กล่าวถึง: AndroidFFmpeg จาก Appunite

มีคำแนะนำทีละขั้นตอนอย่างละเอียดในการคัดลอก / วางไปยังบรรทัดคำสั่งสำหรับคนขี้เกียจอย่างฉัน))


3

ฉันมีปัญหาเดียวกันฉันพบคำตอบส่วนใหญ่ที่นี่ล้าสมัย ฉันลงเอยด้วยการเขียน wrapper บน FFMPEG เพื่อเข้าถึงจาก Android ด้วยรหัสบรรทัดเดียว

https://github.com/madhavanmalolan/ffmpegandroidlibrary


1
ดูเหมือนว่าคุณได้รวบรวม FFmpeg v2.8.4 มีแผนจะอัพเกรด FFmpeg หรือไม่? เรากำลังมองหาโซลูชัน Android ที่มี FFmpeg เวอร์ชันล่าสุด (อาจเป็น 3.2 หรือ 3.4)
sappu

ใช่. ฉันตั้งใจจะย้ายไปที่ 3.x github.com/madhavanmalolan/ffmpegandroidlibrary/milestone/1 คุณสามารถลองแก้ไขสคริปต์สร้างได้ที่นี่และรวบรวม 3.4 github.com/madhavanmalolan/ffmpegandroidlibrary/wiki/…
Madhavan Malolan

ขอบคุณ @Madhvan ฉันกำลังสร้างห้องสมุด ffmpeg บน windows เพียงแค่สงสัยว่าสิ่งที่ทุกคนจะต้องมีการเปลี่ยนแปลงในgithub.com/madhavanmalolan/ffmpegandroidlibrary/wiki/…เพื่อสร้าง?
sappu

1

ก่อนอื่นให้เพิ่มการพึ่งพาของไลบรารี FFmpeg

implementation 'com.writingminds:FFmpegAndroid:0.3.2'

จากนั้นโหลดกิจกรรม

FFmpeg ffmpeg;
    private void trimVideo(ProgressDialog progressDialog) {

    outputAudioMux = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES).getAbsolutePath()
            + "/VidEffectsFilter" + "/" + new SimpleDateFormat("ddMMyyyy_HHmmss").format(new Date())
            + "filter_apply.mp4";

    if (startTrim.equals("")) {
        startTrim = "00:00:00";
    }

    if (endTrim.equals("")) {
        endTrim = timeTrim(player.getDuration());
    }

    String[] cmd = new String[]{"-ss", startTrim + ".00", "-t", endTrim + ".00", "-noaccurate_seek", "-i", videoPath, "-codec", "copy", "-avoid_negative_ts", "1", outputAudioMux};


    execFFmpegBinary1(cmd, progressDialog);
    }



    private void execFFmpegBinary1(final String[] command, ProgressDialog prpg) {

    ProgressDialog progressDialog = prpg;

    try {
        ffmpeg.execute(command, new ExecuteBinaryResponseHandler() {
            @Override
            public void onFailure(String s) {
                progressDialog.dismiss();
                Toast.makeText(PlayerTestActivity.this, "Fail to generate video", Toast.LENGTH_SHORT).show();
                Log.d(TAG, "FAILED with output : " + s);
            }

            @Override
            public void onSuccess(String s) {
                Log.d(TAG, "SUCCESS wgith output : " + s);

//                    pathVideo = outputAudioMux;
                String finalPath = outputAudioMux;
                videoPath = outputAudioMux;
                Toast.makeText(PlayerTestActivity.this, "Storage Path =" + finalPath, Toast.LENGTH_SHORT).show();

                Intent intent = new Intent(PlayerTestActivity.this, ShareVideoActivity.class);
                intent.putExtra("pathGPU", finalPath);
                startActivity(intent);
                finish();
                MediaScannerConnection.scanFile(PlayerTestActivity.this, new String[]{finalPath}, new String[]{"mp4"}, null);

            }

            @Override
            public void onProgress(String s) {
                Log.d(TAG, "Started gcommand : ffmpeg " + command);
                progressDialog.setMessage("Please Wait video triming...");
            }

            @Override
            public void onStart() {
                Log.d(TAG, "Startedf command : ffmpeg " + command);

            }

            @Override
            public void onFinish() {
                Log.d(TAG, "Finished f command : ffmpeg " + command);
                progressDialog.dismiss();
            }
        });
    } catch (FFmpegCommandAlreadyRunningException e) {
        // do nothing for now
    }
}

  private void loadFFMpegBinary() {
    try {
        if (ffmpeg == null) {
            ffmpeg = FFmpeg.getInstance(this);
        }
        ffmpeg.loadBinary(new LoadBinaryResponseHandler() {
            @Override
            public void onFailure() {
                showUnsupportedExceptionDialog();
            }

            @Override
            public void onSuccess() {
                Log.d("dd", "ffmpeg : correct Loaded");
            }
        });
    } catch (FFmpegNotSupportedException e) {
        showUnsupportedExceptionDialog();
    } catch (Exception e) {
        Log.d("dd", "EXception no controlada : " + e);
    }
}

private void showUnsupportedExceptionDialog() {
    new AlertDialog.Builder(this)
            .setIcon(android.R.drawable.ic_dialog_alert)
            .setTitle("Not Supported")
            .setMessage("Device Not Supported")
            .setCancelable(false)
            .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    finish();
                }
            })
            .create()
            .show();

}

ใช้ฟีเจอร์อื่นโดย FFmpeg ด้วย

===> merge audio to video
String[] cmd = new String[]{"-i", yourRealPath, "-i", arrayList.get(posmusic).getPath(), "-map", "1:a", "-map", "0:v", "-codec", "copy", "-shortest", outputcrop};


===> Flip vertical :
String[] cm = new String[]{"-i", yourRealPath, "-vf", "vflip", "-codec:v", "libx264", "-preset", "ultrafast", "-codec:a", "copy", outputcrop1};


===> Flip horizontally :  
String[] cm = new String[]{"-i", yourRealPath, "-vf", "hflip", "-codec:v", "libx264", "-preset", "ultrafast", "-codec:a", "copy", outputcrop1};


===> Rotate 90 degrees clockwise:
String[] cm=new String[]{"-i", yourRealPath, "-c", "copy", "-metadata:s:v:0", "rotate=90", outputcrop1};


===> Compress Video
String[] complexCommand = {"-y", "-i", yourRealPath, "-strict", "experimental", "-vcodec", "libx264", "-preset", "ultrafast", "-crf", "24", "-acodec", "aac", "-ar", "22050", "-ac", "2", "-b", "360k", "-s", "1280x720", outputcrop1};


===> Speed up down video
String[] complexCommand = {"-y", "-i", yourRealPath, "-filter_complex", "[0:v]setpts=2.0*PTS[v];[0:a]atempo=0.5[a]", "-map", "[v]", "-map", "[a]", "-b:v", "2097k", "-r", "60", "-vcodec", "mpeg4", outputcrop1};
String[] complexCommand = {"-y", "-i", yourRealPath, "-filter_complex", "[0:v]setpts=1.0*PTS[v];[0:a]atempo=1.0[a]", "-map", "[v]", "-map", "[a]", "-b:v", "2097k", "-r", "60", "-vcodec", "mpeg4", outputcrop1};
String[] complexCommand = {"-y", "-i", yourRealPath, "-filter_complex", "[0:v]setpts=0.75*PTS[v];[0:a]atempo=1.5[a]", "-map", "[v]", "-map", "[a]", "-b:v", "2097k", "-r", "60", "-vcodec", "mpeg4", outputcrop1};
String[] complexCommand = {"-y", "-i", yourRealPath, "-filter_complex", "[0:v]setpts=0.5*PTS[v];[0:a]atempo=2.0[a]", "-map", "[v]", "-map", "[a]", "-b:v", "2097k", "-r", "60", "-vcodec", "mpeg4", outputcrop1};



===> Add two mp3 files 

StringBuilder sb = new StringBuilder();
sb.append("-i ");
sb.append(textSngname);
sb.append(" -i ");
sb.append(mAudioFilename);
sb.append(" -filter_complex [0:0][1:0]concat=n=2:v=0:a=1[out] -map [out] ");
sb.append(finalfile);
---> ffmpeg.execute(sb.toString().split(" "), new ExecuteBinaryResponseHandler()




===> Add three mp3 files

StringBuilder sb = new StringBuilder();
sb.append("-i ");
sb.append(firstSngname);
sb.append(" -i ");
sb.append(textSngname);
sb.append(" -i ");
sb.append(mAudioFilename);
sb.append(" -filter_complex [0:0][1:0][2:0]concat=n=3:v=0:a=1[out] -map [out] ");
sb.append(finalfile);
---> ffmpeg.execute(sb.toString().split(" "), new ExecuteBinaryResponseHandler()
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.