Android'de FFmpeg


207

Android'de derlenmiş FFmpeg (libffmpeg.so) var. Şimdi RockPlayer gibi bir uygulama oluşturmak veya FFmpeg'i çağırmak için mevcut Android multimedya çerçevesini kullanmak zorundayım.

  1. Android / StageFright'ta FFmpeg'i entegre etmeye ilişkin adımlarınız / prosedürleriniz / kodunuz / örneğiniz var mı?

  2. Lütfen bu kütüphaneyi multimedya oynatımı için nasıl kullanabileceğim konusunda rehberlik edebilir misiniz?

  3. Ben zaten FFmpeg beslemek ve kodunu çözmek / render almak için gereken ses ve video taşıma akışları var bir gereksinimim var. IOMX API'leri OMX tabanlı olduğundan ve buraya FFmpeg ekleyemediğinden bunu Android'de nasıl yapabilirim?

  4. Ayrıca oynatma için kullanılması gereken FFmpeg API'leri ile ilgili dokümanları da bulamadım.


7
bu ilginç, ben de merak ediyorum
Axarydax

5
.f dosyalarını almak için ffmpeg'i nasıl derlediniz? lütfen takip ettiğiniz adımları paylaşır mısınız? Cygwin-1.7.9 ve ndk r5 ile pencereler üzerinde çalışıyorum. Lütfen bana yardım et.
Swathi EP

İşte Android için nispeten yeni bir FFmpeg: sourceforge.net/projects/ffmpeg4android
slhck

@slhck Yukarıdaki bağlantıdan ffmpeg kodunu indirdim ve derlemeye çalıştım ama .so dosyalarını alamıyorum. birçok sorun gösteriyor ..
RAJESH

lütfen bana yardım et: stackoverflow.com/questions/14157030/… , ben bu işlevi dahil etmek ve çalıştırmak için nerede bilmiyorum! .....
TharakaNirmana

Yanıtlar:


109

İşte ffmpeg'in Android'de çalışmasını sağlamak için attığım adımlar:

  1. Android için ffmpeg statik kütüphaneleri oluşturun. Bu, Android Build Sistemi kullanılarak olvaffe'in ffmpeg android portu ( libffmpeg ) inşa edilerek elde edildi . Kaynakların altına / dışına ve uzağa yerleştirilmesi yeterlidir . Ffmpeg kütüphaneleri onlara bağlı olduğu için Android yapısından da biyonik (libc) ve zlib (libz) ayıklamanız gerekir.make
  2. Android NDK kullanarak ffmpeg işlevselliğini saran dinamik bir kütüphane oluşturun . NDK ile nasıl çalışılacağı konusunda birçok belge var. Temel olarak ffmpeg dışında ihtiyacınız olan işlevselliği JNI aracılığıyla etkileşime girebilecek bir kütüphaneye aktarmak için bazı C / C ++ kodları yazmanız gerekir. NDK, 1. adımda oluşturduğunuz statik kitaplıklara kolayca bağlanmanıza izin verir, sadece Android'e benzer bir satır ekleyin. Mk:LOCAL_STATIC_LIBRARIES := libavcodec libavformat libavutil libc libz

  3. Java kaynaklarınızdan ffmpeg sarma dinamik kitaplığını kullanın. JNI hakkında yeterince belge var, iyi olmalısın.

Oynatma için ffmpeg kullanarak ilgili olarak, birçok örnek (ffmpeg ikili kendisi iyi bir örnektir) vardır burada 'temel öğretici s. En iyi belgeler başlıklarda bulunabilir.

İyi şanslar :)


7
Android için ffmpeg oluşturmak için bu cevaba oldukça az bağlantı var. Bu hala en iyi çözüm mü? Android Derleme Sistemi bağlantısı koptu - bunun ne olması gerekiyor? NDK ile inşa etmeye yardımcı olacak bir takım araç setleri var. Ancak hepsi benim için çeşitli yapı hataları ile başarısız ve biraz eski görünüyor. Birisinin sadece inşa edilmiş bir statik ffmpeg lib'i yayınlamamasının bir nedeni var mı?
Rob Lourens

7
Kendi sorumu yanıtlamak için, bu repoyu
Rob Lourens

68

Çeşitli nedenlerden ötürü, Multimedia verimlilikten ödün vermeden göreve ulaşmak açısından hiç kolay olmadı. ffmpeg her geçen gün bunu geliştirme çabasıdır. Farklı kodek ve kapsayıcı biçimlerini destekler.

Şimdi bu kütüphanenin nasıl kullanılacağı sorusunu cevaplamak için , buraya yazmanın o kadar basit olmadığını söyleyebilirim. Ama size aşağıdaki yollarla rehberlik edebilirim .

1) Kaynak kodunun ffmpeg dizininde output_example.c veya api_example.c'ye olursunuz . Burada, kodlama / kod çözmenin yapıldığı kodu görebilirsiniz. Ffmpeg içindeki hangi API'leri çağırmanız gerektiği hakkında bir fikir edineceksiniz. Bu senin ilk adımın olacak.

2) Dolphin player Android için açık kaynaklı bir projedir. Şu anda hatalar var ama geliştiriciler sürekli çalışıyor. Bu projede, araştırmanıza devam etmek için kullanabileceğiniz tüm kurulum hazır. İşte projenin code.google.com adresinden bir bağlantısı veya bir terminalde " git clone https://code.google.com/p/dolphin-player/ " komutunu çalıştırın . P ve P86 adında iki proje görebilirsiniz. Bunlardan herhangi birini kullanabilirsiniz.

Sunmak istediğiniz ekstra ipucu, ffmpeg kodunu oluştururken, build.sh içinde, kullanmak istediğiniz biçimlerin muxers / demuxers / encoders / dekoderlerini etkinleştirmeniz gerektiğidir. Aksi takdirde ilgili kod kütüphanelere dahil edilmeyecektir. Bunu fark etmem çok zaman aldı. Bu yüzden sizinle paylaşmayı düşündüm.

Birkaç Temel Bilgi: Bir video dosyası dediğimizde, örneğin: avi, hem ses hem de videonun birleşimidir

Video dosyası = Video + Ses


Video = Codec + Muxer + Demuxer

codec = kodlayıcı + Kod çözücü

=> Video = kodlayıcı + kod çözücü + Muxer + Demuxer (Mpeg4 + Mpeg4 + avi + avi - Avi kabı örneği)


Ses = Codec + Muxer + Demuxer

codec = kodlayıcı + Kod çözücü

=> Ses = kodlayıcı + kod çözücü + Muxer + Demuxer (mp2 + mp2 + avi + avi - Avi kabı örneği)


Codec (ad, en * co * der / * dec * oder birleşiminden türetilir), yalnızca bir çerçeveyi kodlamak / kodunu çözmek için kullanılan algoritmaları tanımlayan biçimin bir parçasıdır. AVI bir codec bileşeni değil, Mpeg4'ün Video codec bileşenini ve mp2'nin Audio codec bileşenini kullanan bir kapsayıcıdır.

Muxer / demuxer, kareleri kodlama / kod çözme sırasında kullanılan bir dosyadan birleştirmek / ayırmak için kullanılır.

Bu yüzden avi formatını kullanmak istiyorsanız, Video bileşenleri + Ses bileşenleri'ni etkinleştirmeniz gerekir.

Örneğin, avi için aşağıdakileri etkinleştirmeniz gerekir. mpeg4 Enkoder, mpeg4 dekoder, mp2 kodlayıcı, mp2 dekoder, avi muxer, avi demuxer.

phewwwwwww ...

Programlı olarak build.sh aşağıdaki kodu içermelidir:

--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)

Umarım tüm bunlardan sonra seni daha fazla karıştırmazdım ...

Teşekkürler, herhangi bir yardıma ihtiyaç, lütfen bana bildirin.


1
Hey, bu bilgi için sana çok teşekkür etmek istiyorum, gerçekten bana çok yardımcı oldun, daha sonra ihtiyacım olursa bana yardım etmen mümkün mü? Teşekkür ederim!
idish

Sizi skype / MSN veya başka bir sohbet platformu aracılığıyla ekleyebilir miyim lütfen? Bununla ilgili birkaç sorum var, teşekkür ederim.
idish

2
Elbette..!! Ama on-line varlığım biraz düşük .. Çok gerekli olmadığı sürece skype oturum açmıyorum. Önemli şeyler için bana mail atabilirsin. E-posta: mantykuma@gmail.com
mk ..

13

Bulduğum en kolay, kullanımı kolay uygulama theguardianproject ekibi tarafından yapıldı: https://github.com/guardianproject/android-ffmpeg


Emin değilim, sanırım, yeni iOS sürümünde bunu kırabilecek hiçbir şey aklıma gelmiyor. Bunu gönderdiğimde hala 10.7 veya 10.6'm vardı
Guy

biliyor musunuz, nasıl JNI uygulamasını kullanarak 3gp sese dönüştürebilirsiniz
Mr.G

11

Android NDK kullanarak X264 ve FFMPEG'i yapılandırmak ve oluşturmak için küçük bir proje yaptım. Eksik olan ana şey, Java aracılığıyla erişilebilir olmasını sağlamak için iyi bir JNI arayüzüdür, ancak bu kolay kısımdır (nispeten). JNI arayüzünü kendi kullanımım için iyi hale getirmeye başladığımda, bunu içeri iteceğim.

Olvaffe'nin inşa sistemine göre yararı, kütüphaneleri oluşturmak için Android.mk dosyalarına ihtiyaç duymaması, sadece normal makefiles ve araç zincirini kullanmasıdır. Bu, FFMPEG veya X264'ten yeni bir değişiklik yaptığınızda çalışmayı durdurma olasılığını azaltır.

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


Nick, projeniz OS X 10.7 libx264.a (common.o) üzerinde x264_param_parse': common.c:(.text+0x2864): undefined reference to derlemiyor: _DefaultRuneLocale 'collect2 işlevinde: 1 çıkış durumu döndürdü: *** [x264] Hata 1
Yuriy Solovyov


6

FFMPEG başvurumu yapmak için bu projeyi kullandım ( https://github.com/hiteshsondhi88/ffmpeg-android-java ) bu yüzden hiçbir şey derlememe gerek yok. Android uygulamalarımızda FFMPEG kullanmanın kolay yolu olduğunu düşünüyorum.

Hakkında daha fazla bilgi Http://hiteshsondhi88.github.io/ffmpeg-android-java/ hakkında


3
Bu sarıcı çok çok çok çok çok yavaş. Videoya 200 resim 50-60 saniye sürüyor. . . ancak normalde ffmpeg bu görevi 4-5 saniye içinde işler.
Arsen Sench

Bu proje artık çalışmıyor. Başka kaynaklarınız var mı?
Ajeet

@ArsenSench Başka çözümünüz var mı?
Akash Dubey

3

Orada Android uygulamalarında (özellikle guadianproject ) diğer birçok FFmpeg'den esinlenerek , bir çözüm buldum (ayrıca Lame desteği ile).

(topal ve FFmpeg: https://github.com/intervigilium/liblame ve http://bambuser.com/opensource )

FFmpeg'i aramak için:

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();

ve konsol çıkışını işlemek için:

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.
        }
    }
}

Guardianproject ile olan deneyiminiz nedir?
XY

3

Bu projeden bahsedilmediğinden garip: Appunite'den AndroidFFmpeg

Benim gibi tembel insanlar için komut satırına kopyalamak / yapıştırmak için oldukça ayrıntılı adım adım talimatlar vardır))


3

Aynı sorunu yaşadım, cevapların çoğunu tarihli buldum. Android'den tek bir kod satırı ile erişmek için FFMPEG üzerine bir sarıcı yazdım.

https://github.com/madhavanmalolan/ffmpegandroidlibrary


1
FFmpeg v2.8.4'ü derlediğiniz anlaşılıyor, FFmpeg'i yükseltmek için herhangi bir plan var mı? FFmpeg'in en son (3.2 veya 3.4 olabilir) sürümüne sahip android çözümünü arıyoruz.
sappu

Evet. Bunu 3.x'e taşımak niyetindeyim github.com/madhavanmalolan/ffmpegandroidlibrary/milestone/1 Burada yapı komut dosyasını değiştirmeye ve 3.4 github.com/madhavanmalolan/ffmpegandroidlibrary/wiki/…
Madhavan Malolan

Teşekkürler @Madhvan. Windows üzerinde ffmpeg kütüphanesi inşa ediyorum. Sadece github.com/madhavanmalolan/ffmpegandroidlibrary/wiki/… adresinde nelerin değiştirilmesi gerektiğini merak mı ediyorsunuz ?
sappu

1

İlk olarak, FFmpeg kütüphanesinin bağımlılığını ekleyin

implementation 'com.writingminds:FFmpegAndroid:0.3.2'

Sonra aktivite yük

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();

}

Ayrıca FFmpeg tarafından başka bir özellik kullanın

===> 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()
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.