直播流开始和停止

This commit is contained in:
2026-07-03 17:58:51 +08:00
parent 4819dbce86
commit 07f634ae05
7 changed files with 188 additions and 9 deletions

View File

@@ -0,0 +1,48 @@
kotlin version: 2.2.10
error message: java.nio.file.AccessDeniedException: C:\Users\Administrator\AppData\Local\kotlin\daemon\kotlin-daemon-client-tsmarker3368904538941318214.tmp
error message: Daemon compilation failed: Could not connect to Kotlin compile daemon
java.lang.RuntimeException: Could not connect to Kotlin compile daemon
at org.jetbrains.kotlin.compilerRunner.GradleKotlinCompilerWork.compileWithDaemon(GradleKotlinCompilerWork.kt:214)
at org.jetbrains.kotlin.compilerRunner.GradleKotlinCompilerWork.compileWithDaemonOrFallbackImpl(GradleKotlinCompilerWork.kt:159)
at org.jetbrains.kotlin.compilerRunner.GradleKotlinCompilerWork.run(GradleKotlinCompilerWork.kt:111)
at org.jetbrains.kotlin.compilerRunner.GradleCompilerRunnerWithWorkers$GradleKotlinCompilerWorkAction.execute(GradleCompilerRunnerWithWorkers.kt:74)
at org.gradle.workers.internal.DefaultWorkerServer.execute(DefaultWorkerServer.java:68)
at org.gradle.workers.internal.NoIsolationWorkerFactory$1$1.create(NoIsolationWorkerFactory.java:64)
at org.gradle.workers.internal.NoIsolationWorkerFactory$1$1.create(NoIsolationWorkerFactory.java:61)
at org.gradle.internal.classloader.ClassLoaderUtils.executeInClassloader(ClassLoaderUtils.java:102)
at org.gradle.workers.internal.NoIsolationWorkerFactory$1.lambda$execute$0(NoIsolationWorkerFactory.java:61)
at org.gradle.workers.internal.AbstractWorker$1.call(AbstractWorker.java:44)
at org.gradle.workers.internal.AbstractWorker$1.call(AbstractWorker.java:41)
at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:209)
at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:204)
at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:66)
at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:59)
at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:166)
at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:59)
at org.gradle.internal.operations.DefaultBuildOperationRunner.call(DefaultBuildOperationRunner.java:53)
at org.gradle.workers.internal.AbstractWorker.executeWrappedInBuildOperation(AbstractWorker.java:41)
at org.gradle.workers.internal.NoIsolationWorkerFactory$1.execute(NoIsolationWorkerFactory.java:58)
at org.gradle.workers.internal.DefaultWorkerExecutor.lambda$submitWork$0(DefaultWorkerExecutor.java:176)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:317)
at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner.runExecution(DefaultConditionalExecutionQueue.java:194)
at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner.access$700(DefaultConditionalExecutionQueue.java:127)
at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner$1.run(DefaultConditionalExecutionQueue.java:169)
at org.gradle.internal.Factories$1.create(Factories.java:30)
at org.gradle.internal.work.DefaultWorkerLeaseService.lambda$withLocksAcquired$0(DefaultWorkerLeaseService.java:269)
at org.gradle.internal.work.ResourceLockStatistics$1.measure(ResourceLockStatistics.java:42)
at org.gradle.internal.work.DefaultWorkerLeaseService.withLocksAcquired(DefaultWorkerLeaseService.java:267)
at org.gradle.internal.work.DefaultWorkerLeaseService.withLocks(DefaultWorkerLeaseService.java:259)
at org.gradle.internal.work.DefaultWorkerLeaseService.runAsWorkerThread(DefaultWorkerLeaseService.java:127)
at org.gradle.internal.work.DefaultWorkerLeaseService.runAsWorkerThread(DefaultWorkerLeaseService.java:132)
at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner.runBatch(DefaultConditionalExecutionQueue.java:164)
at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner.run(DefaultConditionalExecutionQueue.java:133)
at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:572)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:317)
at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:64)
at org.gradle.internal.concurrent.AbstractManagedExecutor$1.run(AbstractManagedExecutor.java:47)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642)
at java.base/java.lang.Thread.run(Thread.java:1583)

View File

@@ -0,0 +1,48 @@
kotlin version: 2.2.10
error message: java.nio.file.AccessDeniedException: C:\Users\Administrator\AppData\Local\kotlin\daemon\kotlin-daemon-client-tsmarker2940944726750836786.tmp
error message: Daemon compilation failed: Could not connect to Kotlin compile daemon
java.lang.RuntimeException: Could not connect to Kotlin compile daemon
at org.jetbrains.kotlin.compilerRunner.GradleKotlinCompilerWork.compileWithDaemon(GradleKotlinCompilerWork.kt:214)
at org.jetbrains.kotlin.compilerRunner.GradleKotlinCompilerWork.compileWithDaemonOrFallbackImpl(GradleKotlinCompilerWork.kt:159)
at org.jetbrains.kotlin.compilerRunner.GradleKotlinCompilerWork.run(GradleKotlinCompilerWork.kt:111)
at org.jetbrains.kotlin.compilerRunner.GradleCompilerRunnerWithWorkers$GradleKotlinCompilerWorkAction.execute(GradleCompilerRunnerWithWorkers.kt:74)
at org.gradle.workers.internal.DefaultWorkerServer.execute(DefaultWorkerServer.java:68)
at org.gradle.workers.internal.NoIsolationWorkerFactory$1$1.create(NoIsolationWorkerFactory.java:64)
at org.gradle.workers.internal.NoIsolationWorkerFactory$1$1.create(NoIsolationWorkerFactory.java:61)
at org.gradle.internal.classloader.ClassLoaderUtils.executeInClassloader(ClassLoaderUtils.java:102)
at org.gradle.workers.internal.NoIsolationWorkerFactory$1.lambda$execute$0(NoIsolationWorkerFactory.java:61)
at org.gradle.workers.internal.AbstractWorker$1.call(AbstractWorker.java:44)
at org.gradle.workers.internal.AbstractWorker$1.call(AbstractWorker.java:41)
at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:209)
at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:204)
at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:66)
at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:59)
at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:166)
at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:59)
at org.gradle.internal.operations.DefaultBuildOperationRunner.call(DefaultBuildOperationRunner.java:53)
at org.gradle.workers.internal.AbstractWorker.executeWrappedInBuildOperation(AbstractWorker.java:41)
at org.gradle.workers.internal.NoIsolationWorkerFactory$1.execute(NoIsolationWorkerFactory.java:58)
at org.gradle.workers.internal.DefaultWorkerExecutor.lambda$submitWork$0(DefaultWorkerExecutor.java:176)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:317)
at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner.runExecution(DefaultConditionalExecutionQueue.java:194)
at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner.access$700(DefaultConditionalExecutionQueue.java:127)
at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner$1.run(DefaultConditionalExecutionQueue.java:169)
at org.gradle.internal.Factories$1.create(Factories.java:30)
at org.gradle.internal.work.DefaultWorkerLeaseService.lambda$withLocksAcquired$0(DefaultWorkerLeaseService.java:269)
at org.gradle.internal.work.ResourceLockStatistics$1.measure(ResourceLockStatistics.java:42)
at org.gradle.internal.work.DefaultWorkerLeaseService.withLocksAcquired(DefaultWorkerLeaseService.java:267)
at org.gradle.internal.work.DefaultWorkerLeaseService.withLocks(DefaultWorkerLeaseService.java:259)
at org.gradle.internal.work.DefaultWorkerLeaseService.runAsWorkerThread(DefaultWorkerLeaseService.java:127)
at org.gradle.internal.work.DefaultWorkerLeaseService.runAsWorkerThread(DefaultWorkerLeaseService.java:132)
at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner.runBatch(DefaultConditionalExecutionQueue.java:164)
at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner.run(DefaultConditionalExecutionQueue.java:133)
at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:572)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:317)
at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:64)
at org.gradle.internal.concurrent.AbstractManagedExecutor$1.run(AbstractManagedExecutor.java:47)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642)
at java.base/java.lang.Thread.run(Thread.java:1583)

View File

@@ -0,0 +1,20 @@
package com.ckkj.defense_device.bean
data class VideoStreamInfo(
val deviceNo: String,
val streamId: String,
val app: String,
val online: Boolean,
val pushUrl: String,
val playToken: String,
val expireAt: String,
val playUrls:playUrls,
val expireSeconds: Int,
)
class playUrls(
val flv: String,
val hls: String,
val rtmp: String,
val rtsp: String,
val webrtc: String,
)

View File

@@ -0,0 +1,5 @@
package com.ckkj.defense_device.bean
data class VideoStreamRequest(
val deviceNo: String
)

View File

@@ -5,7 +5,6 @@ import android.content.res.Configuration
import android.graphics.Color import android.graphics.Color
import android.os.Bundle import android.os.Bundle
import android.util.Log import android.util.Log
import android.view.GestureDetector
import android.view.MotionEvent import android.view.MotionEvent
import android.view.View import android.view.View
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
@@ -22,10 +21,13 @@ import com.gyf.immersionbar.ImmersionBar
import com.shuyu.gsyvideoplayer.builder.GSYVideoOptionBuilder import com.shuyu.gsyvideoplayer.builder.GSYVideoOptionBuilder
import com.shuyu.gsyvideoplayer.listener.GSYSampleCallBack import com.shuyu.gsyvideoplayer.listener.GSYSampleCallBack
import com.shuyu.gsyvideoplayer.utils.OrientationUtils import com.shuyu.gsyvideoplayer.utils.OrientationUtils
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import android.os.Handler import android.os.Handler
import android.os.Looper import android.os.Looper
import com.ckkj.defense_device.bean.VideoStreamInfo
import com.ckkj.defense_device.bean.VideoStreamRequest
import com.ckkj.defense_device.view.MyGSYVideoPlayerLive import com.ckkj.defense_device.view.MyGSYVideoPlayerLive
class LiveVideoActivity : BaseActivity() { class LiveVideoActivity : BaseActivity() {
@@ -47,6 +49,7 @@ class LiveVideoActivity : BaseActivity() {
private var orientationUtils: OrientationUtils? = null private var orientationUtils: OrientationUtils? = null
private val ptzHandler = Handler(Looper.getMainLooper()) private val ptzHandler = Handler(Looper.getMainLooper())
private var currentPtzDirection: String? = null private var currentPtzDirection: String? = null
private var streamUrl: String? = null
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
@@ -90,15 +93,41 @@ class LiveVideoActivity : BaseActivity() {
} }
private fun initVideoPlayer() { private fun initVideoPlayer() {
val videoUrl ="http://220.203.23.195:9090/live/test001.live.flv"
orientationUtils = OrientationUtils(this, binding.exoPlayContextId) orientationUtils = OrientationUtils(this, binding.exoPlayContextId)
orientationUtils?.isEnable = true orientationUtils?.isEnable = true
hidePlayerControls()
fetchStreamUrl()
}
private fun fetchStreamUrl() {
val no = deviceNo ?: return
lifecycleScope.launch {
try {
val response = RetrofitNetwork.getNetworkService().videoStart(VideoStreamRequest(no))
Log.d("直播流开始", "code=${response.code}, msg=${response.msg}")
if (response.code == 200 && response.data != null) {
//flv(http) 支持IjkPlayer最好
//hls(.m3u8) 支持ExoPlayer/Ijk都支持
//rtmp IjkPlayer支持Exo默认不支持
//rtsp IjkPlayer支持
//webrtcGSYVideoPlayer 不支持
streamUrl = response.data.playUrls.flv
Log.d("直播流开始", "获取地址:$streamUrl")
setupVideoPlayer(streamUrl!!)
} else {
Log.e("直播流开始", response.msg)
}
} catch (e: Exception) {
Log.e("直播流开始", "异常", e)
}
}
}
private fun setupVideoPlayer(videoUrl: String) {
GSYVideoOptionBuilder() GSYVideoOptionBuilder()
.setUrl(videoUrl) .setUrl(videoUrl)
.setCacheWithPlay(false) .setCacheWithPlay(false)
.setCacheWithPlay(false)
.setRotateViewAuto(true) .setRotateViewAuto(true)
.setLockLand(false) .setLockLand(false)
.setShowFullAnimation(true) .setShowFullAnimation(true)
@@ -113,13 +142,11 @@ class LiveVideoActivity : BaseActivity() {
override fun onQuitFullscreen(url: String?, vararg objects: Any?) { override fun onQuitFullscreen(url: String?, vararg objects: Any?) {
super.onQuitFullscreen(url, *objects) super.onQuitFullscreen(url, *objects)
orientationUtils?.backToProtVideo() orientationUtils?.backToProtVideo()
} }
}) })
.build(binding.exoPlayContextId) .build(binding.exoPlayContextId)
hidePlayerControls()
binding.exoPlayContextId.startPlayLogic() binding.exoPlayContextId.startPlayLogic()
binding.exoPlayContextId.fullscreenButton.setOnClickListener { binding.exoPlayContextId.fullscreenButton.setOnClickListener {
binding.exoPlayContextId.onPtzControlListener = binding.exoPlayContextId.onPtzControlListener =
@@ -140,7 +167,6 @@ class LiveVideoActivity : BaseActivity() {
orientationUtils?.resolveByClick() orientationUtils?.resolveByClick()
binding.exoPlayContextId.startWindowFullscreen(this, true, true) binding.exoPlayContextId.startWindowFullscreen(this, true, true)
} }
} }
private fun hidePlayerControls() { private fun hidePlayerControls() {
binding.exoPlayContextId.backButton.visibility = View.GONE binding.exoPlayContextId.backButton.visibility = View.GONE
@@ -420,5 +446,18 @@ class LiveVideoActivity : BaseActivity() {
ptzHandler.removeCallbacksAndMessages(null) ptzHandler.removeCallbacksAndMessages(null)
orientationUtils?.releaseListener() orientationUtils?.releaseListener()
binding.exoPlayContextId.release() binding.exoPlayContextId.release()
stopStream()
}
private fun stopStream() {
val no = deviceNo ?: return
GlobalScope.launch {
try {
val response = RetrofitNetwork.getNetworkService().videoStop(no)
Log.d("直播流停止", "videoStop response: code=${response.code}, msg=${response.msg}")
} catch (e: Exception) {
Log.e("直播流停止", "停止推流异常", e)
}
}
} }
} }

View File

@@ -28,6 +28,8 @@ import com.ckkj.defense_device.bean.UpdateUserInfo
import com.ckkj.defense_device.bean.UploadResponse import com.ckkj.defense_device.bean.UploadResponse
import com.ckkj.defense_device.bean.UserInfoBean import com.ckkj.defense_device.bean.UserInfoBean
import com.ckkj.defense_device.bean.VerifyOptionPasswordRequest import com.ckkj.defense_device.bean.VerifyOptionPasswordRequest
import com.ckkj.defense_device.bean.VideoStreamInfo
import com.ckkj.defense_device.bean.VideoStreamRequest
import okhttp3.MultipartBody import okhttp3.MultipartBody
import retrofit2.http.Body import retrofit2.http.Body
import retrofit2.http.DELETE import retrofit2.http.DELETE
@@ -328,5 +330,22 @@ interface ApiService {
@Query("duration") duration: String, @Query("duration") duration: String,
): GetCodeBean<Any> ): GetCodeBean<Any>
/**
* 开始推流
*/
@POST("/app/stream/start")
suspend fun videoStart(
@Body request: VideoStreamRequest
): GetCodeBean<VideoStreamInfo>
/**
* 停止推流
*/
@POST("/app/stream/stop/{deviceNo}")
suspend fun videoStop(
@retrofit2.http.Path("deviceNo") deviceNo: String
): GetCodeBean<Any>
} }

View File

@@ -12,8 +12,8 @@ import java.util.concurrent.TimeUnit
object RetrofitNetwork { object RetrofitNetwork {
private const val DEFAULT_TIMEOUT = 30L private const val DEFAULT_TIMEOUT = 30L
const val BASE_URL = "https://stem-boozy-margarine.ngrok-free.dev" //const val BASE_URL = "https://stem-boozy-margarine.ngrok-free.dev"
//const val BASE_URL = "http://service.reinkun.com:8001" const val BASE_URL = "http://service.reinkun.com:8001"
private var retrofit: Retrofit? = null private var retrofit: Retrofit? = null
private val gson = Gson() private val gson = Gson()