지난 ExoPlayer 포스팅에 이어, 이번엔 libvlc 라이브러리를 가지고 왔다.
해당 라이브러리는 VLC에서 제공하는 외부 라이브러리다.
✅ VLC (Video LAN Clients)
VideoLan Project에서 개발하는 오픈소스 미디어 재생기이며,
자체 코덱 내장 및 높은 호환성으로 현존하는 미디어 플레이어 중 최고라 볼 수 있다.
libvlc는 안드로이드 뿐 아니라, 다양한 플러그인을 지원하기에
우리가 사용해볼 라이브러리는 libvlc-Android 버전이라 볼 수 있다.
라이브러리 경로는 다음과 같다 ↓
친절히도 VLC에서 제공하는 안드로이드 전용 샘플 코드도 존재한다 ↓
위 샘플 코드를 기반으로 예제를 진행해보겠다.
✅ Manifest 권한 추가
AndroidManifest.xml
<uses-permission android:name="android.permission.INTERNET"/>
이전 포스팅과 마찬가지로, 네트워크 스트리밍을 진행할 것이기에 인터넷 권한을 추가해준다.
✅ 의존성 설정
build.gradle.kts (Module:app)
implementation("org.videolan.android:libvlc-all:3.5.1")
최신 버전은 위 라이브러리 링크에서 확인바란다.
✅ 레이아웃 설정
activity_main.xml
<FrameLayout
android:layout_width="match_parent"
android:layout_height="300dp"
>
<org.videolan.libvlc.util.VLCVideoLayout
android:id="@+id/videolayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</FrameLayout>
VLCVideoLayout의 height 값을 수동으로 입력해도 높이가 변하지 않는다.
그렇기에 위 처럼 FrameLayout으로 높이를 지정하고 래핑해줄 수 있다.
✅ RTSP 스트리밍
스트리밍에 필요한 코드는 다음과 같다.
MainActivity.kt
private fun playerInit() {
// 네트워크 스트림 주소를 Uri 형식으로 초기화
val uri = "rtsp://210.99.70.120:1935/live/cctv048.stream".toUri()
// libvlc 및 MediaPlayer 초기화
val libVlc = LibVLC(this)
val mediaPlayer = MediaPlayer(libVlc)
// MediaPlayer와 레이아웃에 선언한 videolayout을 연결
mediaPlayer.attachViews(bind.videolayout, null, false, false)
// libvlc 객체와 스트림 주소로 Media 객체 초기화 후 MediaPlayer에 연결
val media = Media(libVlc, uri)
mediaPlayer.media = media
// Media 릴리즈 후 MediaPlayer 재생
media.release()
mediaPlayer.play()
// 미디어 플레이어에서 발생하는 이벤트 리스너
mediaPlayer.setEventListener {
// MediaPlayer.Event 객체가 던져짐
}
}
override fun onCreate() {
...
playerInit()
}
코드 한 줄마다 주석을 달아놨으니 확인바란다.
간단히 추가 설명이 필요할 것 같은 부분은 MediaPlayer.attachViews() 함수인데,
파라미터를 4개나 받는다.
● attachViews(VLCVideoLayout, DisplayManager, Subtitles, TextureView)
- VLCVideoLayout : 레이아웃 파일에 선언한 VideoLayout을 연결해주면 된다.
- DisplayManager : 렌더링 전환용 변수 옵션을 추가할 수 있다.
- Subtitles : 자막 활성/비활성 값을 Boolean으로 작성한다.
- TextureView : TextureView = true / SurfaceView = false
MediaPlayer.setEventListener에서는 스트리밍 시작 ~ 종료까지의 다양한 이벤트를 수신할 수 있다.
예를 들어 다음과 같이 Event.buffering 로그를 찍어보면
mediaPlayer.setEventListener {
Log.d(TAG, "buffering: ${it.buffering.toInt()}")
}
버퍼링 수치를 확인할 수 있다.
위 스크린샷을 보면 알겠지만, 버퍼링이 100이 되어 영상이 출력되면 다시 0으로 돌아간다.
이 버퍼링 수치를 사용자에게 보여주는 기능을 간단히 만들어본다.
var isLoaded = false
mediaPlayer.setEventListener {
if (!isLoaded) {
when (it.buffering.toInt()) {
0 -> bind.progressbar.visibility = View.VISIBLE
100 -> {
bind.textview.visibility = View.GONE
isLoaded = true
}
else -> {
bind.textview.text = "${it.buffering.toInt()}%"
bind.progressbar.visibility = View.GONE
bind.textview.visibility = View.VISIBLE
}
}
}
}
VideoLayout 중앙에 버퍼링 표시할 TextView를 하나 만들어놓고,
버퍼링 0 → 프로그래스바 표시
버퍼링 1~99 → 버퍼링 수치 표시
버퍼링 100 → 영상만 출력
위와 같이 작성했다.
추후에도 리스너에 버퍼링 0이 계속 호출되므로, Boolean 변수로 체크한다.
✅ 결과
● 스트리밍 연결 중
버퍼링이 0을 벗어날 때까지 프로그래스바가 표시된다.
● 스트리밍 연결 후 버퍼링
프로그래스바가 사라지며 영상 중앙에 버퍼링 숫자%가 올라가고 있는 모습이다.
스트림 연결 상태에 따라서 검정 화면에 버퍼링 숫자%가 표시될 때도 있고,
위 처럼 영상 썸네일이 로드된 후 버퍼링 숫자%가 표시될 때도 있다.
● 스트리밍 연결 성공 후
영상이 재생되는 모습이다.
VLC 플레이어도 명성에 걸맞게 안정적으로 RTSP 스트리밍을 지원한다.
'Android (안드로이드)' 카테고리의 다른 글
[Android] NDK / JNI (1) (2) | 2024.12.04 |
---|---|
[Android] 안드로이드 환경에서 C언어 사용 이유? / Java · C 성능 차이점 (5) | 2024.12.02 |
[Android] ExoPlayer - RTSP 스트리밍 연결 (0) | 2024.11.28 |
[Android] RTSP - 실시간 스트리밍 프로토콜 (0) | 2024.11.27 |
[Android] 앱에서 카메라로 사진 찍고 갤러리에 저장하기 / 이미지뷰 로드하기 (1) | 2024.11.26 |