it-swarm.com.de

Hinzufügen von Wasserzeichen-Bitmap über Video in Android: 4.3 MediaMuxer oder ffmpeg

Hier ist mein Szenario:

  • Laden Sie einen AVI-Film aus dem Internet herunter
  • Öffnen Sie eine Bitmap-Ressource 
  • Überlagern Sie diese Bitmap am unteren Rand des Films in allen Frames im Hintergrund
  • Speichern Sie das Video auf extarnalem Speicher
  • Die Videolänge beträgt normalerweise 15 Sekunden

Kann man dies mit MediaMuxer erreichen? Alle Informationen zu dieser Angelegenheit werden gerne entgegengenommen

Ich habe nach http://bigflake.com/mediacodec/#DecodeEditEncodeTest gesucht (Thanks @fadden) und dort steht: 

"Das Dekodieren des Rahmens und das Kopieren in einen ByteBuffer mit glReadPixels() dauert auf dem Nexus 5 etwa 8 ms, schnell genug, um Mit der Eingabe von 30 Bildern pro Sekunde Schritt zu halten, aber die zum Speichern erforderlichen als PNG-Diskette sind teuer (etwa eine halbe Sekunde) "

Fast 1 Sekunde pro Bild ist also nicht akzeptabel. Ich denke, eine Möglichkeit wäre, jeden Frame als PNG zu speichern, zu öffnen, die Bitmap-Überlagerung hinzuzufügen und dann zu speichern. Dies würde jedoch eine enorme Zeit in Anspruch nehmen. 

Ich frage mich, ob es einen Weg gibt, solche Dinge zu tun:

  1. Videodatei von einem externen Speicher öffnen
  2. Beginnen Sie mit der Dekodierung
  3. Jeder decodierte Frame wird mit der Bitmap-Überlagerung im Speicher geändert
  4. Der Frame wird an einen Encoder gesendet.

Auf iOS habe ich gesehen, dass es eine Möglichkeit gibt, das Original-Audio + Original-Video + ein Bild aufzunehmen und in einen Container einzufügen und dann einfach das Ganze zu kodieren ...

Soll ich zu ffmpeg wechseln? Wie stabil und kompatibel ist ffmpeg? Riskiere ich Kompatibilitätsprobleme mit Android 4.0+ -Geräten? Gibt es eine Möglichkeit, ffmpeg zu verwenden, um dies zu erreichen? Ich bin neu in diesem Bereich und forsche noch immer.


Jahre später edit: 
Jahre sind seit der Frage vergangen, und ffmpeg ist nicht wirklich einfach, eine kommerzielle Software in Bezug auf die Lizenz hinzuzufügen. Wie hat sich das entwickelt? Neuere Versionen von Android sind mit der Standard-SDK mehr dazu in der Lage?


Noch etwas später editieren

Ich habe einige negative Stimmen für die Veröffentlichung von Informationen als Antwort erhalten, also werde ich die ursprüngliche Frage bearbeiten. Hier ist eine großartige Bibliothek, die aus meinen Tests Wasserzeichen auf Video anwendet und dies mit einem Fortschrittscallback macht. Dadurch wird es dem Benutzer viel einfacher, den Fortschritt anzuzeigen, und er verwendet außerdem die Standard-Android-SDKs. https://github.com/MasayukiSuda/Mp4Composer-Android

Diese Bibliothek generiert einen Mp4-Film mit der Android MediaCodec-API und wendet Filter an, skaliert und dreht Mp4.

Beispielcode könnte folgendermaßen aussehen:

new mp4Composer(sourcePath, destinationPath)
        .filter(new GlWatermarkFilter(watermarkBitmap)
        .listener(){
              @Override 
              private void onProgress(double value){}

              @Override 
              private void onCompleted(double value){
                  runOnUiThread( () ->{
                     showSneakbar
                  }
              }

              @Override 
              private void onCancelled(double value){}

              @Override 
              private void onFailed(Exception e){}

        }).start();

Das Testen mit dem Emulator scheint auf Android 8+ gut zu funktionieren, während auf älteren Versionen eine schwarze Videodatei erzeugt wird. Allerdings scheint das Testen auf einem echten Gerät zu funktionieren.

28
Alin

Ich weiß nicht viel über den MediaMuxer, aber ffmpeg unterstützt die Überlagerungsfunktion. FFMPEG verfügt über verschiedene Filter, von denen einer Overlay-Filter ist. Was ich verstehe, ist, dass Sie dem Video ein Bild überlagern möchten (d. H. Png). Sie können das Ausgabeformat einstellen. Sie können die Koordinaten des zu überspielenden Bildes festlegen. 

Z.B.

ffmpeg -i input.avi -i logo.png -filter_complex 'overlay=10:main_h-overlay_h-10' output.avi

Der obige Befehl fügt Overlays logo.png in der input.avi-Videodatei in der linken unteren Ecke hinzu.

Weitere Informationen zu den Filtern finden Sie auf folgender Website.

https://www.ffmpeg.org/ffmpeg-filters.html#overlay-1

Wenn dies eine Lösung für Ihr Problem ist, benötigen Sie den C-Code, der dem obigen Befehl entspricht. Sie müssen auch die Leistung des ffmpeg sehen, da es sich um ein reines Software-Framework handelt.

Ich hoffe, ich habe deine Frage richtig verstanden und das hilft.

19
pragnesh

Wenn Sie dies tun möchten ohne ffmpeg auf einem Android-Gerät:

Beginnen Sie mit: https://github.com/google/grafika

Die Antwort auf Ihre Frage zwischen Play video (PlayMovieActivity.Java) und Record Gl App (RecordFBOActivity.Java)

Schritte:

  1. Richten Sie mInputWindowSurface als Video-Encoder-Eingabefläche ein. 

  2. Dekodieren Sie das Bild aus dem Videostream mit MoviePlayer als (externe) Videotextur.

  3. Zeichnen Sie diese Videotextur auf Fläche.

  4. Zeichnen Sie ein Wasserzeichen auf derselben Oberfläche über der Videotextur.

  5. Benachrichtigen Sie MediaCodec, dass die Oberfläche zum Kodieren bereit ist:

    mVideoEncoder.frameAvailableSoon(); 
    mInputWindowSurface.setPresentationTime(timeStampNanos);
    

    und dann weiter mit Schritt 2.

Vergessen Sie nicht, die Dekodiergeschwindigkeit einzustellen. Entfernen Sie einfach SpeedControlCallback, das im Beispiel auf 60 FPS-Video decodiert ist.

Vorteile dieses Weges:

  1. Media Codec verwendet Hardware-Decoder/Encoder für die Videoverarbeitung. 

  2. Sie können die Bitrate des Ergebnisvideos ändern.

10
AndreyICE

Sie können INDE Media Pack ausprobieren - https://software.intel.com/de-de/articles/intel-inde-media-pack-for-Android-tutorials

Es verfügt über Transcoding/Remuxing-Funktionalität als MediaComposer-Klasse und mehrere Beispieleffekte wie JpegSubstituteEffect - es zeigt, wie ein Videoframe durch ein Bild aus einer JPG-Datei und TextOverlayEffect ersetzt wird, um Text auf dem Videoframe zu überlagern

enter image description here

7
Marlon

Das hat bei mir funktioniert:

ffmpeg -i input.avi -i logo.png -filter_complex 'overlay=10:main_h-overlay_h-10' -strict -2 output.avi

ffmpeg empfahl die Verwendung von -strict -2, um experimentelle Codecs verwenden zu können. Ohne die Einbeziehung funktioniert die oben genannte akzeptierte Antwort nicht.

1
kc ochibili