如何在 android 中玩 SRT(安全可靠传输)?
How to play a SRT (Secure Reliable Transfer) in android?
我想知道是否可以使用安全可靠传输协议播放视频。这种类型的视频以 srt://
开头。我知道 VideoView 只支持 https 和另一个我不记得但不支持 srt 的协议。
谷歌搜索的任何尝试都会产生关于 srt 字幕文件的结果,这不是我要找的。
有谁知道如何在 android 上播放 srt 视频?
如果有人来这里寻找答案,这就是我为使其正常工作所做的工作。我的方法是用于直播,但可以对其进行修改以处理单一文件类型的视频。
我设法实现了一个自定义的 ExoPlayer 数据源,它适用于实时流式传输 SRT。
工厂
class SrtLiveStreamDataSourceFactory(
private val srtUrl: String,
private val port: Int,
private val passPhrase: String? = null
) :
DataSource.Factory {
override fun createDataSource(): DataSource {
return SrtLiveStreamDataSource(srtUrl, port, passPhrase)
}
}
数据源
const val PAYLOAD_SIZE = 1316
class SrtLiveStreamDataSource(
private val srtUrl: String,
private val port: Int,
private val passPhrase: String?
) :
BaseDataSource(/*isNetwork*/true) {
private var socket: Socket? = null
private val byteQueue: Queue<Byte> = LinkedList()
override fun open(dataSpec: DataSpec): Long {
socket = Socket()
socket?.setSockFlag(SockOpt.TRANSTYPE, Transtype.LIVE)
socket?.setSockFlag(SockOpt.PAYLOADSIZE, PAYLOAD_SIZE)
if(passPhrase != null){
socket?.setSockFlag(SockOpt.PASSPHRASE, passPhrase)
}
socket?.connect(srtUrl, port)
return C.LENGTH_UNSET.toLong()
}
/**
* Receives from SRT socket and feeds into a queue. Depending on the length requested
* from exoplayer, that amount of bytes is polled from queue and onto the buffer with the given offset.
*
* You cannot directly receive at the given length from the socket, because SRT uses a
* predetermined payload size that cannot be dynamic
*/
override fun read(buffer: ByteArray, offset: Int, length: Int): Int {
if (length == 0) {
return 0
}
var bytesReceived = 0
if (socket != null) {
val received = socket!!.recv(PAYLOAD_SIZE)
for (byte in received.second /*received byte array*/) {
byteQueue.offer(byte)
}
repeat(length) { index ->
val byte = byteQueue.poll()
if (byte != null) {
buffer[index + offset] = byte
bytesReceived++
}
}
return bytesReceived
}
throw IOException("Couldn't read bytes at offset: $offset")
}
override fun getUri(): Uri? {
return Uri.parse("srt://$srtUrl:$port")
}
override fun close() {
socket?.close()
socket = null
}
}
简单用法
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
val url = SRT_URL_HERE (exclude srt://)
val port = PORT_HERE
val source = ProgressiveMediaSource.Factory(
SrtLiveStreamDataSourceFactory(
url,
port,
),
).createMediaSource(MediaItem.fromUri(Uri.EMPTY))
val player = ExoPlayer.Builder(this)
.build()
player.setMediaSource(source)
binding.playerView.player = player
player.prepare()
player.play()
player.playWhenReady = true
}
}
我想知道是否可以使用安全可靠传输协议播放视频。这种类型的视频以 srt://
开头。我知道 VideoView 只支持 https 和另一个我不记得但不支持 srt 的协议。
谷歌搜索的任何尝试都会产生关于 srt 字幕文件的结果,这不是我要找的。
有谁知道如何在 android 上播放 srt 视频?
如果有人来这里寻找答案,这就是我为使其正常工作所做的工作。我的方法是用于直播,但可以对其进行修改以处理单一文件类型的视频。
我设法实现了一个自定义的 ExoPlayer 数据源,它适用于实时流式传输 SRT。
工厂
class SrtLiveStreamDataSourceFactory(
private val srtUrl: String,
private val port: Int,
private val passPhrase: String? = null
) :
DataSource.Factory {
override fun createDataSource(): DataSource {
return SrtLiveStreamDataSource(srtUrl, port, passPhrase)
}
}
数据源
const val PAYLOAD_SIZE = 1316
class SrtLiveStreamDataSource(
private val srtUrl: String,
private val port: Int,
private val passPhrase: String?
) :
BaseDataSource(/*isNetwork*/true) {
private var socket: Socket? = null
private val byteQueue: Queue<Byte> = LinkedList()
override fun open(dataSpec: DataSpec): Long {
socket = Socket()
socket?.setSockFlag(SockOpt.TRANSTYPE, Transtype.LIVE)
socket?.setSockFlag(SockOpt.PAYLOADSIZE, PAYLOAD_SIZE)
if(passPhrase != null){
socket?.setSockFlag(SockOpt.PASSPHRASE, passPhrase)
}
socket?.connect(srtUrl, port)
return C.LENGTH_UNSET.toLong()
}
/**
* Receives from SRT socket and feeds into a queue. Depending on the length requested
* from exoplayer, that amount of bytes is polled from queue and onto the buffer with the given offset.
*
* You cannot directly receive at the given length from the socket, because SRT uses a
* predetermined payload size that cannot be dynamic
*/
override fun read(buffer: ByteArray, offset: Int, length: Int): Int {
if (length == 0) {
return 0
}
var bytesReceived = 0
if (socket != null) {
val received = socket!!.recv(PAYLOAD_SIZE)
for (byte in received.second /*received byte array*/) {
byteQueue.offer(byte)
}
repeat(length) { index ->
val byte = byteQueue.poll()
if (byte != null) {
buffer[index + offset] = byte
bytesReceived++
}
}
return bytesReceived
}
throw IOException("Couldn't read bytes at offset: $offset")
}
override fun getUri(): Uri? {
return Uri.parse("srt://$srtUrl:$port")
}
override fun close() {
socket?.close()
socket = null
}
}
简单用法
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
val url = SRT_URL_HERE (exclude srt://)
val port = PORT_HERE
val source = ProgressiveMediaSource.Factory(
SrtLiveStreamDataSourceFactory(
url,
port,
),
).createMediaSource(MediaItem.fromUri(Uri.EMPTY))
val player = ExoPlayer.Builder(this)
.build()
player.setMediaSource(source)
binding.playerView.player = player
player.prepare()
player.play()
player.playWhenReady = true
}
}