mirror of
https://github.com/tapframe/NuvioStreaming.git
synced 2026-05-02 13:44:54 +00:00
added header support
This commit is contained in:
parent
767fd2ff87
commit
18fa11fd88
6 changed files with 53 additions and 5 deletions
|
|
@ -22,6 +22,7 @@ class MPVView @JvmOverloads constructor(
|
||||||
private var pendingDataSource: String? = null
|
private var pendingDataSource: String? = null
|
||||||
private var isPaused: Boolean = true
|
private var isPaused: Boolean = true
|
||||||
private var surface: Surface? = null
|
private var surface: Surface? = null
|
||||||
|
private var httpHeaders: Map<String, String>? = null
|
||||||
|
|
||||||
// Event listener for React Native
|
// Event listener for React Native
|
||||||
var onLoadCallback: ((duration: Double, width: Int, height: Int) -> Unit)? = null
|
var onLoadCallback: ((duration: Double, width: Int, height: Int) -> Unit)? = null
|
||||||
|
|
@ -51,6 +52,7 @@ class MPVView @JvmOverloads constructor(
|
||||||
|
|
||||||
// If a data source was set before surface was ready, load it now
|
// If a data source was set before surface was ready, load it now
|
||||||
pendingDataSource?.let { url ->
|
pendingDataSource?.let { url ->
|
||||||
|
applyHttpHeaders()
|
||||||
loadFile(url)
|
loadFile(url)
|
||||||
pendingDataSource = null
|
pendingDataSource = null
|
||||||
}
|
}
|
||||||
|
|
@ -93,7 +95,7 @@ class MPVView @JvmOverloads constructor(
|
||||||
|
|
||||||
// Hardware decoding - use mediacodec-copy to allow subtitle overlay
|
// Hardware decoding - use mediacodec-copy to allow subtitle overlay
|
||||||
// 'mediacodec-copy' copies frames to CPU memory which enables subtitle blending
|
// 'mediacodec-copy' copies frames to CPU memory which enables subtitle blending
|
||||||
MPVLib.setOptionString("hwdec", "mediacodec-copy")
|
MPVLib.setOptionString("hwdec", "auto")
|
||||||
MPVLib.setOptionString("hwdec-codecs", "all")
|
MPVLib.setOptionString("hwdec-codecs", "all")
|
||||||
|
|
||||||
// Audio output
|
// Audio output
|
||||||
|
|
@ -105,6 +107,9 @@ class MPVView @JvmOverloads constructor(
|
||||||
MPVLib.setOptionString("cache", "yes")
|
MPVLib.setOptionString("cache", "yes")
|
||||||
MPVLib.setOptionString("cache-secs", "30")
|
MPVLib.setOptionString("cache-secs", "30")
|
||||||
|
|
||||||
|
// Network options
|
||||||
|
MPVLib.setOptionString("network-timeout", "60") // 60 second timeout
|
||||||
|
|
||||||
// Subtitle configuration - CRITICAL for Android
|
// Subtitle configuration - CRITICAL for Android
|
||||||
MPVLib.setOptionString("sub-auto", "fuzzy") // Auto-load subtitles
|
MPVLib.setOptionString("sub-auto", "fuzzy") // Auto-load subtitles
|
||||||
MPVLib.setOptionString("sub-visibility", "yes") // Make subtitles visible by default
|
MPVLib.setOptionString("sub-visibility", "yes") // Make subtitles visible by default
|
||||||
|
|
@ -155,7 +160,7 @@ class MPVView @JvmOverloads constructor(
|
||||||
val MPV_FORMAT_DOUBLE = 5
|
val MPV_FORMAT_DOUBLE = 5
|
||||||
|
|
||||||
MPVLib.observeProperty("time-pos", MPV_FORMAT_DOUBLE)
|
MPVLib.observeProperty("time-pos", MPV_FORMAT_DOUBLE)
|
||||||
MPVLib.observeProperty("duration", MPV_FORMAT_DOUBLE)
|
MPVLib.observeProperty("duration/full", MPV_FORMAT_DOUBLE) // Use /full for complete HLS duration
|
||||||
MPVLib.observeProperty("pause", MPV_FORMAT_FLAG)
|
MPVLib.observeProperty("pause", MPV_FORMAT_FLAG)
|
||||||
MPVLib.observeProperty("paused-for-cache", MPV_FORMAT_FLAG)
|
MPVLib.observeProperty("paused-for-cache", MPV_FORMAT_FLAG)
|
||||||
MPVLib.observeProperty("eof-reached", MPV_FORMAT_FLAG)
|
MPVLib.observeProperty("eof-reached", MPV_FORMAT_FLAG)
|
||||||
|
|
@ -179,12 +184,31 @@ class MPVView @JvmOverloads constructor(
|
||||||
|
|
||||||
fun setDataSource(url: String) {
|
fun setDataSource(url: String) {
|
||||||
if (isMpvInitialized) {
|
if (isMpvInitialized) {
|
||||||
|
// Apply headers before loading the file
|
||||||
|
applyHttpHeaders()
|
||||||
loadFile(url)
|
loadFile(url)
|
||||||
} else {
|
} else {
|
||||||
pendingDataSource = url
|
pendingDataSource = url
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun setHeaders(headers: Map<String, String>?) {
|
||||||
|
httpHeaders = headers
|
||||||
|
Log.d(TAG, "Headers set: $headers")
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun applyHttpHeaders() {
|
||||||
|
httpHeaders?.let { headers ->
|
||||||
|
if (headers.isNotEmpty()) {
|
||||||
|
// Format headers for MPV: comma-separated "Key: Value" pairs
|
||||||
|
val headerList = headers.map { (key, value) -> "$key: $value" }
|
||||||
|
val headerString = headerList.joinToString(",")
|
||||||
|
Log.d(TAG, "Applying HTTP headers: $headerString")
|
||||||
|
MPVLib.setOptionString("http-header-fields", headerString)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun setPaused(paused: Boolean) {
|
fun setPaused(paused: Boolean) {
|
||||||
isPaused = paused
|
isPaused = paused
|
||||||
if (isMpvInitialized) {
|
if (isMpvInitialized) {
|
||||||
|
|
@ -341,10 +365,10 @@ class MPVView @JvmOverloads constructor(
|
||||||
Log.d(TAG, "Property $property = $value (Double)")
|
Log.d(TAG, "Property $property = $value (Double)")
|
||||||
when (property) {
|
when (property) {
|
||||||
"time-pos" -> {
|
"time-pos" -> {
|
||||||
val duration = MPVLib.getPropertyDouble("duration") ?: 0.0
|
val duration = MPVLib.getPropertyDouble("duration/full") ?: MPVLib.getPropertyDouble("duration") ?: 0.0
|
||||||
onProgressCallback?.invoke(value, duration)
|
onProgressCallback?.invoke(value, duration)
|
||||||
}
|
}
|
||||||
"duration" -> {
|
"duration/full", "duration" -> {
|
||||||
val width = MPVLib.getPropertyInt("width") ?: 0
|
val width = MPVLib.getPropertyInt("width") ?: 0
|
||||||
val height = MPVLib.getPropertyInt("height") ?: 0
|
val height = MPVLib.getPropertyInt("height") ?: 0
|
||||||
onLoadCallback?.invoke(value, width, height)
|
onLoadCallback?.invoke(value, width, height)
|
||||||
|
|
@ -384,7 +408,7 @@ class MPVView @JvmOverloads constructor(
|
||||||
Log.d(TAG, "MPV_EVENT_END_FILE")
|
Log.d(TAG, "MPV_EVENT_END_FILE")
|
||||||
|
|
||||||
// Heuristic: If duration is effectively 0 at end of file, it's a load error
|
// Heuristic: If duration is effectively 0 at end of file, it's a load error
|
||||||
val duration = MPVLib.getPropertyDouble("duration") ?: 0.0
|
val duration = MPVLib.getPropertyDouble("duration/full") ?: MPVLib.getPropertyDouble("duration") ?: 0.0
|
||||||
val timePos = MPVLib.getPropertyDouble("time-pos") ?: 0.0
|
val timePos = MPVLib.getPropertyDouble("time-pos") ?: 0.0
|
||||||
val eofReached = MPVLib.getPropertyBoolean("eof-reached") ?: false
|
val eofReached = MPVLib.getPropertyBoolean("eof-reached") ?: false
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -163,4 +163,21 @@ class MpvPlayerViewManager(
|
||||||
fun setResizeMode(view: MPVView, resizeMode: String?) {
|
fun setResizeMode(view: MPVView, resizeMode: String?) {
|
||||||
view.setResizeMode(resizeMode ?: "contain")
|
view.setResizeMode(resizeMode ?: "contain")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ReactProp(name = "headers")
|
||||||
|
fun setHeaders(view: MPVView, headers: com.facebook.react.bridge.ReadableMap?) {
|
||||||
|
if (headers != null) {
|
||||||
|
val headerMap = mutableMapOf<String, String>()
|
||||||
|
val iterator = headers.keySetIterator()
|
||||||
|
while (iterator.hasNextKey()) {
|
||||||
|
val key = iterator.nextKey()
|
||||||
|
headers.getString(key)?.let { value ->
|
||||||
|
headerMap[key] = value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
view.setHeaders(headerMap)
|
||||||
|
} else {
|
||||||
|
view.setHeaders(null)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
1
mpv-android
Submodule
1
mpv-android
Submodule
|
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit 118cd1ed3d498265e44230e5dbb015bdd59f9dad
|
||||||
|
|
@ -487,6 +487,7 @@ const AndroidVideoPlayer: React.FC = () => {
|
||||||
<View style={{ flex: 1, backgroundColor: 'black' }}>
|
<View style={{ flex: 1, backgroundColor: 'black' }}>
|
||||||
<VideoSurface
|
<VideoSurface
|
||||||
processedStreamUrl={currentStreamUrl}
|
processedStreamUrl={currentStreamUrl}
|
||||||
|
headers={headers}
|
||||||
volume={volume}
|
volume={volume}
|
||||||
playbackSpeed={speedControl.playbackSpeed}
|
playbackSpeed={speedControl.playbackSpeed}
|
||||||
resizeMode={playerState.resizeMode}
|
resizeMode={playerState.resizeMode}
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ export interface MpvPlayerRef {
|
||||||
|
|
||||||
export interface MpvPlayerProps {
|
export interface MpvPlayerProps {
|
||||||
source: string;
|
source: string;
|
||||||
|
headers?: { [key: string]: string };
|
||||||
paused?: boolean;
|
paused?: boolean;
|
||||||
volume?: number;
|
volume?: number;
|
||||||
rate?: number;
|
rate?: number;
|
||||||
|
|
@ -92,6 +93,7 @@ const MpvPlayer = forwardRef<MpvPlayerRef, MpvPlayerProps>((props, ref) => {
|
||||||
ref={nativeRef}
|
ref={nativeRef}
|
||||||
style={[styles.container, props.style]}
|
style={[styles.container, props.style]}
|
||||||
source={props.source}
|
source={props.source}
|
||||||
|
headers={props.headers}
|
||||||
paused={props.paused ?? true}
|
paused={props.paused ?? true}
|
||||||
volume={props.volume ?? 1.0}
|
volume={props.volume ?? 1.0}
|
||||||
rate={props.rate ?? 1.0}
|
rate={props.rate ?? 1.0}
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ import { ResizeModeType } from '../../utils/playerTypes';
|
||||||
|
|
||||||
interface VideoSurfaceProps {
|
interface VideoSurfaceProps {
|
||||||
processedStreamUrl: string;
|
processedStreamUrl: string;
|
||||||
|
headers?: { [key: string]: string };
|
||||||
volume: number;
|
volume: number;
|
||||||
playbackSpeed: number;
|
playbackSpeed: number;
|
||||||
resizeMode: ResizeModeType;
|
resizeMode: ResizeModeType;
|
||||||
|
|
@ -35,6 +36,7 @@ interface VideoSurfaceProps {
|
||||||
|
|
||||||
export const VideoSurface: React.FC<VideoSurfaceProps> = ({
|
export const VideoSurface: React.FC<VideoSurfaceProps> = ({
|
||||||
processedStreamUrl,
|
processedStreamUrl,
|
||||||
|
headers,
|
||||||
volume,
|
volume,
|
||||||
playbackSpeed,
|
playbackSpeed,
|
||||||
resizeMode,
|
resizeMode,
|
||||||
|
|
@ -100,6 +102,7 @@ export const VideoSurface: React.FC<VideoSurfaceProps> = ({
|
||||||
<MpvPlayer
|
<MpvPlayer
|
||||||
ref={mpvPlayerRef}
|
ref={mpvPlayerRef}
|
||||||
source={streamUrl}
|
source={streamUrl}
|
||||||
|
headers={headers}
|
||||||
paused={paused}
|
paused={paused}
|
||||||
volume={volume}
|
volume={volume}
|
||||||
rate={playbackSpeed}
|
rate={playbackSpeed}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue