I have this code to export frames to video and it works fine, but I don’t quite understand how I can add audio.
public class VideoExport {
private MediaMuxer muxer;
private MediaCodec codec;
private MediaCodec.BufferInfo bufferInfo;
private int trackIndex;
private boolean muxerStarted;
private int frameCount;
private int fps;
private boolean recording;
private String savePath,fileName;
private int w,h;
public VideoExport() {
trackIndex=-1;
muxerStarted=false;
frameCount=0;
fps=24;
recording=false;
savePath="/storage/emulated/0/Movies/";
fileName="video";
w=100;
h=100;
}
void setSize(int w,int h) {
this.w=(w<2)?2:w-(w%2);
this.h=(h<2)?2:h-(h%2);
}
void setName(String fileName) {
this.fileName=fileName;
}
void setSavePath(String savePath) {
this.savePath=savePath;
}
void setFps(int fps) {
this.fps=fps;
}
public void startRecording(){
if(!recording){
recording=true;
frameCount=0;
setupMediaMuxer();
}
else{
println();
println("can't start recording while recording");
}
}
void setupMediaMuxer() {
try {
// Настройка файла для сохранения
File outputFile = new File(savePath+fileName+".mp4");
muxer=new MediaMuxer(outputFile.getAbsolutePath(),
MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4);
// Настройка формата видео
MediaFormat format=
MediaFormat.createVideoFormat("video/avc",w,h);
format.setInteger(MediaFormat.KEY_COLOR_FORMAT,21);
format.setInteger(MediaFormat.KEY_BIT_RATE,10000000);
format.setInteger(MediaFormat.KEY_FRAME_RATE,fps);
format.setString(MediaFormat.KEY_PROFILE,"Main");
format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL,1);
// Создание и настройка кодека для H.264
codec = MediaCodec.createEncoderByType("video/avc");
codec.configure(format,null,null,
MediaCodec.CONFIGURE_FLAG_ENCODE);
codec.start();
bufferInfo = new MediaCodec.BufferInfo();
} catch (Exception e) {
e.printStackTrace();
}
}
void encodeFrame(PImage frame) {
try {
// Подготовка данных для кадра
int inputBufferIndex=codec.dequeueInputBuffer(10000);
if(inputBufferIndex>=0) {
ByteBuffer inputBuffer=
codec.getInputBuffer(inputBufferIndex);
inputBuffer.clear();
inputBuffer.put(getFrameData(frame));
codec.queueInputBuffer(inputBufferIndex,0,
inputBuffer.limit(),frameCount*1000000/fps,0);
}
// Запись кадра в выходное видео
int outputBufferIndex=
codec.dequeueOutputBuffer(bufferInfo,10000);
while(outputBufferIndex>=0) {
ByteBuffer outputBuffer=
codec.getOutputBuffer(outputBufferIndex);
if(!muxerStarted) {
MediaFormat newFormat=codec.getOutputFormat();
trackIndex=muxer.addTrack(newFormat);
muxer.start();
muxerStarted=true;
}
muxer.writeSampleData(
trackIndex,outputBuffer,bufferInfo);
codec.releaseOutputBuffer(outputBufferIndex,false);
outputBufferIndex=
codec.dequeueOutputBuffer(bufferInfo,10000);
}
frameCount++;
} catch (Exception e) {
e.printStackTrace();
}
}
public void stopRecording(){
if(recording){
codec.stop();
codec.release();
muxer.stop();
muxer.release();
recording=false;
}
else{
println();
println("Can't stop recording before it has started.");
}
}
ByteBuffer getFrameData(PImage frame) {
frame.loadPixels();
ByteBuffer buffer = ByteBuffer.allocate(w*h*3/2);
int yIndex=0;
int uvIndex=w*h;
for(int j=0;j<h;j++) {
for(int i=0;i<w;i++) {
int argb=frame.pixels[j*w+i];
int r=(argb>>16)&0xFF;
int g=(argb>>8)&0xFF;
int b=argb&0xFF;
int y=(int)(0.257*r+0.504*g+0.098*b+16);
int u=(int)(-0.148*r-0.291*g+0.439*b+128);
int v=(int)(0.439*r-0.368*g-0.071*b+128);
buffer.put(yIndex++,(byte)(y&0xFF));
if(j%2==0&&i%2==0) {
buffer.put(uvIndex++,(byte)(u&0xFF));
buffer.put(uvIndex++,(byte)(v&0xFF));
}
}
}
return buffer;
}
public boolean isRecording() {
return recording;
}
}
Example of using:
import android.media.*;
import java.io.*;
import java.nio.*;
import java.io.File;
VideoExport vid;
void setup(){
size(720,720);
vid = new VideoExport();
vid.setSize(720,720);
vid.setName("my video");
vid.setFps(12);
vid.startRecording();
}
void draw() {
background(255);
fill(255,0,0);
noStroke();
ellipse(width/2,height/2+frameCount,100,100);
fill(150);
text(vid.isRecording()+"",100,100);
// Запись кадра
if(frameCount<=48){
vid.encodeFrame(get());
}
else if(frameCount==48+1){
vid.stopRecording();
}
}
I don’t know much about MediaMuxer, I tried to add audio to muxer with MediaExtractor but I get errors. And so far I’m stuck at this point. I would be very grateful if you can help me!