Skip to content

Commit

Permalink
feat(*): add support for srt
Browse files Browse the repository at this point in the history
  • Loading branch information
ThibaultBee committed Sep 30, 2024
1 parent fac6567 commit 3e0fdec
Show file tree
Hide file tree
Showing 7 changed files with 98 additions and 30 deletions.
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
  [![badge](https://img.shields.io/github/stars/apivideo/api.video-android-live-stream?style=social)](https://github.com/apivideo/api.video-android-live-stream)
  [![badge](https://img.shields.io/discourse/topics?server=https%3A%2F%2Fcommunity.api.video)](https://community.api.video)
![](https://github.com/apivideo/.github/blob/main/assets/apivideo_banner.png)
<h1 align="center">Android RTMP live stream client</h1>
<h1 align="center">Android RTMP and SRT live stream client</h1>

[api.video](https://api.video) is the video infrastructure for product builders. Lightning fast
video APIs for integrating, scaling, and managing on-demand & low latency live streaming features in
Expand Down Expand Up @@ -154,8 +154,8 @@ You can check device supported configurations by using the helper: `Helper`

We are using external library

| Plugin | README |
| ------ | ------ |
| Plugin | README |
|---------------------------------------------------------|------------------------------------------------------------------------------|
| [StreamPack](https://github.com/ThibaultBee/StreamPack) | [README.md](https://github.com/ThibaultBee/StreamPack/blob/master/README.md) |

## Sample application
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,11 +76,11 @@ class Configuration(context: Context) {
class Endpoint(private val sharedPref: SharedPreferences, private val resources: Resources) {
var url: String = ""
get() = sharedPref.getString(
resources.getString(R.string.rtmp_endpoint_url_key),
resources.getString(R.string.server_url_key),
field
)!!

var streamKey: String = ""
get() = sharedPref.getString(resources.getString(R.string.rtmp_stream_key_key), field)!!
get() = sharedPref.getString(resources.getString(R.string.stream_key_key), field)!!
}
}
10 changes: 5 additions & 5 deletions example/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,11 @@
<string name="audio_enable_echo_canceler_key">audio_enable_echo_canceler_key</string>
<string name="audio_enable_noise_suppressor_key">audio_enable_noise_suppressor_key</string>
<string name="audio_enable_noise_suppressor">Enable noise suppressor</string>
<string name="default_rtmp_endpoint">rtmp://broadcast.api.video/s/</string>
<string name="rtmp_endpoint_url_key">rtmp_address_key</string>
<string name="rtmp_endpoint_url">RTMP endpoint</string>
<string name="rtmp_stream_key_key">rtmp_stream_key_key</string>
<string name="rtmp_stream_key">Stream key</string>
<string name="default_server_url">rtmp://broadcast.api.video/s/</string>
<string name="server_url_key">server_url_key</string>
<string name="server_url">RTMP or SRT server URL</string>
<string name="stream_key_key">stream_key_key</string>
<string name="stream_key">RTMP Stream key or SRT stream id</string>
<string name="permissions">Permissions</string>
<string name="permission_not_granted">Permissions not granted: leaving!</string>
</resources>
10 changes: 5 additions & 5 deletions example/src/main/res/xml/preferences.xml
Original file line number Diff line number Diff line change
Expand Up @@ -62,15 +62,15 @@

<PreferenceCategory app:title="@string/endpoint">
<EditTextPreference
android:defaultValue="@string/default_rtmp_endpoint"
app:key="@string/rtmp_endpoint_url_key"
app:title="@string/rtmp_endpoint_url"
android:defaultValue="@string/default_server_url"
app:key="@string/server_url_key"
app:title="@string/server_url"
app:useSimpleSummaryProvider="true" />

<EditTextPreference
android:defaultValue=""
app:key="@string/rtmp_stream_key_key"
app:title="@string/rtmp_stream_key"
app:key="@string/stream_key_key"
app:title="@string/stream_key"
app:useSimpleSummaryProvider="true" />
</PreferenceCategory>
</PreferenceScreen>
1 change: 1 addition & 0 deletions livestream/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ dependencies {
implementation "io.github.thibaultbee.streampack:streampack-core:$streamPackVersion"
implementation "io.github.thibaultbee.streampack:streampack-ui:$streamPackVersion"
implementation "io.github.thibaultbee.streampack:streampack-extension-rtmp:$streamPackVersion"
implementation "io.github.thibaultbee.streampack:streampack-extension-srt:$streamPackVersion"

testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.2.1'
Expand Down
95 changes: 81 additions & 14 deletions livestream/src/main/java/video/api/livestream/ApiVideoLiveStream.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,17 @@ package video.api.livestream

import android.Manifest
import android.content.Context
import android.net.Uri
import android.util.Log
import androidx.annotation.RequiresPermission
import io.github.thibaultbee.streampack.core.data.mediadescriptor.MediaDescriptor
import io.github.thibaultbee.streampack.core.data.mediadescriptor.UriMediaDescriptor
import io.github.thibaultbee.streampack.core.internal.endpoints.MediaSinkType
import io.github.thibaultbee.streampack.core.streamers.callbacks.DefaultCameraCallbackStreamer
import io.github.thibaultbee.streampack.core.streamers.interfaces.ICallbackStreamer
import io.github.thibaultbee.streampack.core.streamers.interfaces.startStream
import io.github.thibaultbee.streampack.core.utils.extensions.isBackCamera
import io.github.thibaultbee.streampack.core.utils.extensions.isFrontCamera
import io.github.thibaultbee.streampack.ext.srt.data.mediadescriptor.SrtMediaDescriptor
import kotlinx.coroutines.*
import video.api.livestream.enums.CameraFacingDirection
import video.api.livestream.interfaces.IConnectionListener
Expand Down Expand Up @@ -277,31 +279,96 @@ constructor(
}

/**
* Start a new RTMP stream.
* Start a new RTMP or SRT stream.
*
* @param streamKey RTMP stream key. For security purpose, you must not expose it.
* @param url RTMP Url. Default value (not set or null) is api.video RTMP broadcast url.
* Example of RTMP server url:
* ```
* rtmp://broadcast.api.video/s
* ```
*
* Example of SRT server url:
* ```
* srt://broadcast.api.video:6200
* ```
* Other query parameters will be ignored.
*
* @param streamKey The RTMP stream key or SRT stream id. For security purpose, you must not expose it.
* @param url The RTMP or SRT server Url. Default value (not set or null) is api.video RTMP broadcast url.
* @see [stopStreaming]
*/
fun startStreaming(
streamKey: String,
url: String = context.getString(R.string.default_rtmp_url),
url: String = context.getString(R.string.default_server_url),
) {
require(!isStreaming) { "Stream is already running" }
require(streamKey.isNotEmpty()) { "Stream key must not be empty" }
require(url.isNotEmpty()) { "Url must not be empty" }
require(audioConfig != null) { "Audio config must be set" }
require(videoConfig != null) { "Video config must be set" }
requireNotNull(audioConfig) { "Audio config must be set" }
requireNotNull(videoConfig) { "Video config must be set" }

val descriptor = if (url.startsWith("srt://")) {
val uri = Uri.parse(url)
SrtMediaDescriptor(
host = requireNotNull(uri.host),
port = uri.port,
streamId = streamKey
)
} else {
UriMediaDescriptor(url.addTrailingSlashIfNeeded() + streamKey)
}

startStreaming(descriptor)
}

/**
* Start a new RTMP or SRT stream.
*
* Example of RTMP url:
* ```
* rtmp://broadcast.api.video/s/{streamKey}
* ```
*
* Example of SRT url:
* ```
* srt://broadcast.api.video:6200?streamid={streamKey}
* ```
*
* Get the stream key from the api.video dashboard or through the API.
*
* @param url The RTMP or SRT server Url with stream key (RTMP) or stream id (SRT).
* @see [stopStreaming]
*/
fun startStreaming(
url: String
) {
require(!isStreaming) { "Stream is already running" }
require(url.isNotEmpty()) { "Url must not be empty" }
requireNotNull(audioConfig) { "Audio config must be set" }
requireNotNull(videoConfig) { "Video config must be set" }

startStreaming(UriMediaDescriptor(url))
}

/**
* Start a new RTMP or SRT stream.
*
* @param descriptor The media descriptor
* @see [stopStreaming]
*/
private fun startStreaming(
descriptor: MediaDescriptor
) {
require(!isStreaming) { "Stream is already running" }
requireNotNull(audioConfig) { "Audio config must be set" }
requireNotNull(videoConfig) { "Video config must be set" }

val descriptor = UriMediaDescriptor(url.addTrailingSlashIfNeeded() + streamKey)
require(descriptor.type.sinkType == MediaSinkType.RTMP) { "URL must be RTMP" }
require((descriptor.type.sinkType == MediaSinkType.RTMP) || (descriptor.type.sinkType == MediaSinkType.SRT)) { "URL must be RTMP or SRT" }

try {
streamer.startStream(url)
} catch (e: Exception) {
streamer.close()
connectionListener.onConnectionFailed("$e")
throw e
streamer.startStream(descriptor)
} catch (t: Throwable) {
connectionListener.onConnectionFailed("$t")
throw t
}
}

Expand Down
2 changes: 1 addition & 1 deletion livestream/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="default_rtmp_url">rtmp://broadcast.api.video/s/</string>
<string name="default_server_url">rtmp://broadcast.api.video/s/</string>
</resources>

0 comments on commit 3e0fdec

Please sign in to comment.