MediaMuxer video-Datei-Größe zu reduzieren (re-komprimieren, verringern Sie die Auflösung)
Ich bin auf der Suche nach effizienten Weg zur Verringerung der einige video-Gewicht (als File
, für den upload) und die offensichtliche Antwort ist: ermöglicht das reduzieren der Auflösung! (fullHD-oder 4K nicht notwendig, einfaches HD reicht mir) ich habe versucht, viele Möglichkeiten, die arbeiten sollten durch eine Menge von APIs (benötigt 10) und der beste Weg war, mit android-ffmpeg-java, ABER... auf meine ziemlich schnell fast-aktuelle Flaggschiff-Gerät ganze Prozess dauert etwa length_of_video*4 Sekunden und auch diese lib Gewicht ist 9 Mb, dieser Betrag erhöht sich meine app Größe... No wai! (12 Mb auf 1 Mb ist schönes Ergebnis, aber immer noch zu viele Fehler)
So, ich habe beschlossen, den Einsatz von nativen Android Möglichkeiten, dies zu tun, MediaMuxer
und MediaCodec
- Sie sind von API18 und API16 erstellt (ältere Geräte-Nutzer: tut mir Leid; aber oft haben Sie auch "lower-res" - Kamera). Unter Methode fast funktioniert - MediaMuxer
NICHT respektieren MediaFormat.KEY_WIDTH
und MediaFormat.KEY_HEIGHT
- extrahiert File
ist "re-komprimiert", das Gewicht ist ein bisschen kleiner, aber die Auflösung ist die gleiche wie im original-video File
...
So, Frage: Wie komprimieren und re-Skalierung/ändern der Auflösung von video mit MediaMuxer
und anderen zugehörigen Klassen und Methoden?
public File getCompressedFile(String videoPath) throws IOException{
MediaExtractor extractor = new MediaExtractor();
extractor.setDataSource(videoPath);
int trackCount = extractor.getTrackCount();
String filePath = videoPath.substring(0, videoPath.lastIndexOf(File.separator));
String[] splitByDot = videoPath.split("\\.");
String ext="";
if(splitByDot!=null && splitByDot.length>1)
ext = splitByDot[splitByDot.length-1];
String fileName = videoPath.substring(videoPath.lastIndexOf(File.separator)+1,
videoPath.length());
if(ext.length()>0)
fileName=fileName.replace("."+ext, "_out."+ext);
else
fileName=fileName.concat("_out");
final File outFile = new File(filePath, fileName);
if(!outFile.exists())
outFile.createNewFile();
MediaMuxer muxer = new MediaMuxer(outFile.getAbsolutePath(),
MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4);
HashMap<Integer, Integer> indexMap = new HashMap<Integer, Integer>(trackCount);
for (int i = 0; i < trackCount; i++) {
extractor.selectTrack(i);
MediaFormat format = extractor.getTrackFormat(i);
String mime = format.getString(MediaFormat.KEY_MIME);
if(mime!=null && mime.startsWith("video")){
int currWidth = format.getInteger(MediaFormat.KEY_WIDTH);
int currHeight = format.getInteger(MediaFormat.KEY_HEIGHT);
format.setInteger(MediaFormat.KEY_WIDTH, currWidth>currHeight ? 960 : 540);
format.setInteger(MediaFormat.KEY_HEIGHT, currWidth>currHeight ? 540 : 960);
//API19 MediaFormat.KEY_MAX_WIDTH and KEY_MAX_HEIGHT
format.setInteger("max-width", format.getInteger(MediaFormat.KEY_WIDTH));
format.setInteger("max-height", format.getInteger(MediaFormat.KEY_HEIGHT));
}
int dstIndex = muxer.addTrack(format);
indexMap.put(i, dstIndex);
}
boolean sawEOS = false;
int bufferSize = 256 * 1024;
int offset = 100;
ByteBuffer dstBuf = ByteBuffer.allocate(bufferSize);
MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
muxer.start();
while (!sawEOS) {
bufferInfo.offset = offset;
bufferInfo.size = extractor.readSampleData(dstBuf, offset);
if (bufferInfo.size < 0) {
sawEOS = true;
bufferInfo.size = 0;
} else {
bufferInfo.presentationTimeUs = extractor.getSampleTime();
bufferInfo.flags = extractor.getSampleFlags();
int trackIndex = extractor.getSampleTrackIndex();
muxer.writeSampleData(indexMap.get(trackIndex), dstBuf,
bufferInfo);
extractor.advance();
}
}
muxer.stop();
muxer.release();
return outFile;
}
PS. viele nützliche Sachen über muxer hier, obigen code Basen auf MediaMuxerTest.java
Methode cloneMediaUsingMuxer
Du musst angemeldet sein, um einen Kommentar abzugeben.
Den MediaMuxer nicht beteiligt ist, in der Kompression oder Skalierung des Videos. Alle es tut, ist, nehmen Sie die H. 264-Ausgabe von MediaCodec und wickeln Sie es in ein .mp4-Datei wrapper.
Blick auf den code, Sie sind das extrahieren von NAL-Einheiten mit MediaExtractor und sofort wieder einwickeln von Ihnen mit MediaMuxer. Dieser soll extrem schnell sein und haben keinen Einfluss auf das video selbst, denn Sie sind einfach re-wrappen der H. 264.
Skaliert das video, das Sie brauchen, um zu Dekodieren, das video mit MediaCodec decoder, Fütterung der NAL-Einheiten aus MediaExtractor in es, und re-encode es mit MediaCodec encoder, vorbei an den Rahmen, um eine MediaMuxer.
Sie gefunden haben bigflake.com; siehe auch Grafika. Weder dieser hat genau das, was du suchst, aber die verschiedenen Teile sind vorhanden.
Es ist am besten zu Dekodieren, um eine Fläche, nicht ein ByteBuffer. Dies erfordert API-18, aber für Vernunft ist es am besten zu vergessen, dass MediaCodec gab vor dann. Und Sie müssen API-18 für MediaMuxer sowieso.
Surface
mit mehreren en - und de-Coder 🙂Können Sie versuchen, Intel INDE Medien für Mobile, tutorials,https://software.intel.com/en-us/articles/intel-inde-media-pack-for-android-tutorials. Es ist ein Beispiel, das zeigt, wie es zu transcode=komprimieren Sie video-Dateien.
Können Sie einstellen, kleinere Auflösung und /oder bitrate der Ausgabe erhalten Sie kleinere Dateien
https://github.com/INDExOS/media-for-mobile/blob/master/Android/samples/apps/src/com/intel/inde/mp/samples/ComposerTranscodeCoreActivity.java