Reputation: 452
I'd like to be able to stream the video from my webcam to an Android app with a latency below 500ms, on my local network.
To capture and send the video over the network, I use ffmpeg.
ffmpeg -f v4l2 -i /dev/video0 -preset ultrafast -tune zerolatency -vcodec libx264 -an -vf format=yuv420p -f mpegts udp://192.168.1.155:5000
This command takes the webcam as an input, convert it and send it to a device using the mpegts protocol.
This is not a requirement, if another technique could work, I could change the way I send the video.
I am able to read the video on another PC from the local network with a latency below 500 ms, using commands like
gst-launch-1.0 -v udpsrc port=5000 ! video/mpegts ! tsdemux ! h264parse ! avdec_h264 ! fpsdisplaysink sync=false
or
mpv udp://0.0.0.0:5000 --no-cache --untimed --no-demuxer-thread --video-sync=audio --vd-lavc-threads=1
So it is possible to have this range of latency.
I'd like to have the same thing on Android.
Here are my tries to do that.
After looking at the different players available on Android studio, it seems like Exoplayer is the go-to choice.
I tried different options indicated in the live-streaming documentation, but I always end up with a stream taking seconds to start and with a latency of seconds.
I tried to add a Button to seek to the default position of the windows, but it results in a loading of several seconds.
DefaultExtractorsFactory extractorsFactory =
new DefaultExtractorsFactory()
.setTsExtractorFlags(DefaultTsPayloadReaderFactory.FLAG_IGNORE_AAC_STREAM);
player = new SimpleExoPlayer.Builder(this)
.setMediaSourceFactory(
new DefaultMediaSourceFactory(this, extractorsFactory))
.setLoadControl(new DefaultLoadControl.Builder()
.setBufferDurationsMs(DefaultLoadControl.DEFAULT_MIN_BUFFER_MS, DefaultLoadControl.DEFAULT_MAX_BUFFER_MS, 200, 200)
.build())
.build();
MyPlayerView playerView = findViewById(R.id.player_view);
// Bind the player to the view.
playerView.setPlayer(player);
// Build the media item.
MediaItem mediaItem = new MediaItem.Builder()
.setUri(Uri.parse("udp://0.0.0.0:5000"))
.setLiveMaxOffsetMs(500)
.setLiveTargetOffsetMs(0)
.setLiveMinOffsetMs(0)
.build();
// Set the media item to be played.
player.setMediaItem(mediaItem);
// Prepare the player.
player.setPlayWhenReady(true);
player.prepare();
//player.seekToDefaultPosition();
This issue is about the same issue and the conclusion was that Exoplayer was not fit for this use case.
I'll be honest, ultra low-latency like this isn't ExoPlayer's main use-case
Another try was to use the Vlc library.
But I was unable to have the same low latency stream as with the two previous players with Vlc.
I tried changing the preferences of Vlc to stream as fast as possible as described here
Input/Codecs -> x264 preset: ultrafast - zerolatency
Input/Codecs -> Access Module: UDP input
Input/Codecs -> Clock Jitter: 500
Audio: disable audio
I also tried reducing the different buffers.
However, I still have a latency of more than 1 seconds with that.
Another try was to create a react-native project to use the different players available here.
One player that seemed promising was react-native-gstreamer because it uses gstreamer which is able to stream with low latency (gst-launch command).
But the library is now outdated.
There were other tries, but none were successful.
Is there a problem with one of my approaches ?
And if not, Is there a player on Android (that I missed) which is able to achieve low latency stream like gstream or mpv on linux ?
Upvotes: 2
Views: 2324
Reputation: 36
I do not know a native low latency player in Android.
However you can use a WebView
in Android Studio and use a player in the web.
With this solution I streamed the webcam of my pc to my phone (in the local network) with livecam.
They use websockets to transmit the video frame by frame, which is not ideal. With this method I had 370 ms of latency.
Upvotes: 2