How to decrease the latency of the RTP streaming with ffmpeg in Android?
How to decrease the latency of the RTP streaming with ffmpeg in Android?
I'm creating a App that do a RTP streaming. It uses a ParcelFileDescriptor pipe pair, where a MediaRecorder writes in the pipe while the ffmpeg receives the audio from the pipe and sends by RTP.
In my desktop, using the same wifi router, I receive the RTP stream using ffplay, and it has a delay between 5s ~ 10s.
I tried capture audio using ffmpeg in Android, but itsn't possible. I tried to use ffplay -fflags nobuffer, use MIC as source, change the encoder, etc.
I need the lowest delay possible. How can I do it?
The code:
public class MainActivity extends AppCompatActivity implements View.OnClickListener
MediaRecorder mediaRecorder;
AudioRecord record;
MediaPlayer mediaPlayer;
ParcelFileDescriptor pipePair;
ParcelFileDescriptor pipeRead;
ParcelFileDescriptor pipeWrite;
Process ffmpegProc;
// Requesting permission to RECORD_AUDIO
private boolean permissionsAccepted = false;
private String permissions =
Manifest.permission.RECORD_AUDIO,
Manifest.permission.INTERNET,
Manifest.permission.ACCESS_NETWORK_STATE
;
private static final int REQUEST_PERMISSIONS = 200;
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String permissions, @NonNull int grantResults)
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode)
case REQUEST_PERMISSIONS:
permissionsAccepted = grantResults[0] == PackageManager.PERMISSION_GRANTED;
break;
if (!permissionsAccepted ) finish();
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ActivityCompat.requestPermissions(this, permissions, REQUEST_PERMISSIONS);
TextView hello = (TextView) findViewById(R.id.hello);
hello.setOnClickListener(new View.OnClickListener()
@Override
public void onClick(View view)
Toast.makeText(MainActivity.this, "Clicado",Toast.LENGTH_SHORT)
.show();
copiarFFMpeg();
);
private void executarFFMpeg(final String cmd, ParcelFileDescriptor read)
try
ffmpegProc = Runtime.getRuntime().exec(cmd);
catch (IOException e)
e.printStackTrace();
(new Thread(new Runnable()
@Override
public void run()
try
InputStream inStream = ffmpegProc.getInputStream();
InputStreamReader sReader = new InputStreamReader(inStream);
BufferedReader bufferedReader = new BufferedReader(sReader);
String line;
while ((line = bufferedReader.readLine()) != null)
Log.d("FFMPEG",line);
catch (IOException e)
e.printStackTrace();
)).start();
(new Thread(new Runnable()
@Override
public void run()
byte buffer = new byte[8192];
int read = 0;
OutputStream ffmpegInput = ffmpegProc.getOutputStream();
FileInputStream reader = new FileInputStream(pipeRead.getFileDescriptor());
try
while (true)
if (reader.available()>0)
read = reader.read(buffer);
ffmpegInput.write(buffer, 0, read);
ffmpegInput.flush();
else
Thread.sleep(10);
catch (InterruptedException e)
e.printStackTrace();
catch (IOException e)
e.printStackTrace();
onDestroy();
)).start();
Log.d("FFMPEG","Executado");
private boolean estaExecutando(Process ffmpegProc)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
return ffmpegProc.isAlive();
else
try
ffmpegProc.exitValue();
return false;
catch (Exception e)
return true;
private void criarMediaRecorder()
if (pipeWrite != null)
try
//ffplay.exe -protocol_whitelist rtp,file,udp ..file.sdp
mediaRecorder = new MediaRecorder();
mediaRecorder.setAudioSource(MediaRecorder.AudioSource.VOICE_COMMUNICATION);
mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.AAC_ADTS);
mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
//mediaRecorder.setAudioChannels(2);
mediaRecorder.setOutputFile(pipeWrite.getFileDescriptor());
mediaRecorder.prepare();
mediaRecorder.start();
Log.d("MREC","MediaRecorder criado");
catch (Exception e)
e.printStackTrace();
private void criarPipe()
try
pipePair =ParcelFileDescriptor.createPipe();
catch (IOException e)
Log.e("PIPE","Deu zica na criação do pipe");
e.printStackTrace();
finish();
pipeRead = new ParcelFileDescriptor(pipePair[0]);
pipeWrite = new ParcelFileDescriptor(pipePair[1]);
private void copiarFFMpeg()
FFmpeg ffmpeg = FFmpeg.getInstance(this);
try
ffmpeg.loadBinary(new LoadBinaryResponseHandler()
@Override
public void onStart()
Log.d("FFMPEG","Iniciar cópia");
@Override
public void onFailure()
Log.e("FFMPEG","Cópia falhou");
@Override
public void onSuccess()
Log.d("FFMPEG","Cópiado com sucesso");
criarPipe();
//mediaRecorder.start();
File ffmpegBin = new File(getFilesDir().getAbsolutePath()+"/ffmpeg");
String cmd = new String
ffmpegBin.getAbsolutePath(),
"-re",
"-thread_queue_size","4",
"-i","pipe:",
//"-c:a","libx264",
//"-preset","veryfast",
//"-tune","zerolatency",
"-f",
"rtp",
"rtp://192.168.0.33:1234"
;
executarFFMpeg(cmd, pipeRead);
criarMediaRecorder();
@Override
public void onFinish()
);
catch (FFmpegNotSupportedException e)
// Handle if FFmpeg is not supported by device
Log.e("FFMPEG", "Não sou suportado :/");
@Override
protected void onDestroy()
super.onDestroy();
@Override
public void onClick(View view)
The command:
ffplay rtp://192.168.0.33:1234
ffplay -fflags nobuffer rtp://192.168.0.33:1234
By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.