mirror of
https://github.com/streamyfin/streamyfin.git
synced 2026-01-15 15:48:05 +00:00
Merge branch 'develop' into fix/external-sub-selection
Some checks failed
🏗️ Build Apps / 🤖 Build Android APK (Phone) (push) Has been cancelled
🏗️ Build Apps / 🤖 Build Android APK (TV) (push) Has been cancelled
🏗️ Build Apps / 🍎 Build iOS IPA (Phone) (push) Has been cancelled
🏗️ Build Apps / 🍎 Build iOS IPA (Phone - Unsigned) (push) Has been cancelled
🔒 Lockfile Consistency Check / 🔍 Check bun.lock and package.json consistency (push) Has been cancelled
🛡️ CodeQL Analysis / 🔎 Analyze with CodeQL (actions) (push) Has been cancelled
🛡️ CodeQL Analysis / 🔎 Analyze with CodeQL (javascript-typescript) (push) Has been cancelled
🏷️🔀Merge Conflict Labeler / 🏷️ Labeling Merge Conflicts (push) Has been cancelled
🚦 Security & Quality Gate / 📝 Validate PR Title (push) Has been cancelled
🚦 Security & Quality Gate / 🔍 Vulnerable Dependencies (push) Has been cancelled
🚦 Security & Quality Gate / 🚑 Expo Doctor Check (push) Has been cancelled
🚦 Security & Quality Gate / 🔍 Lint & Test (check) (push) Has been cancelled
🚦 Security & Quality Gate / 🔍 Lint & Test (format) (push) Has been cancelled
🚦 Security & Quality Gate / 🔍 Lint & Test (lint) (push) Has been cancelled
🚦 Security & Quality Gate / 🔍 Lint & Test (typecheck) (push) Has been cancelled
Some checks failed
🏗️ Build Apps / 🤖 Build Android APK (Phone) (push) Has been cancelled
🏗️ Build Apps / 🤖 Build Android APK (TV) (push) Has been cancelled
🏗️ Build Apps / 🍎 Build iOS IPA (Phone) (push) Has been cancelled
🏗️ Build Apps / 🍎 Build iOS IPA (Phone - Unsigned) (push) Has been cancelled
🔒 Lockfile Consistency Check / 🔍 Check bun.lock and package.json consistency (push) Has been cancelled
🛡️ CodeQL Analysis / 🔎 Analyze with CodeQL (actions) (push) Has been cancelled
🛡️ CodeQL Analysis / 🔎 Analyze with CodeQL (javascript-typescript) (push) Has been cancelled
🏷️🔀Merge Conflict Labeler / 🏷️ Labeling Merge Conflicts (push) Has been cancelled
🚦 Security & Quality Gate / 📝 Validate PR Title (push) Has been cancelled
🚦 Security & Quality Gate / 🔍 Vulnerable Dependencies (push) Has been cancelled
🚦 Security & Quality Gate / 🚑 Expo Doctor Check (push) Has been cancelled
🚦 Security & Quality Gate / 🔍 Lint & Test (check) (push) Has been cancelled
🚦 Security & Quality Gate / 🔍 Lint & Test (format) (push) Has been cancelled
🚦 Security & Quality Gate / 🔍 Lint & Test (lint) (push) Has been cancelled
🚦 Security & Quality Gate / 🔍 Lint & Test (typecheck) (push) Has been cancelled
This commit is contained in:
@@ -430,6 +430,57 @@ class MPVLayerRenderer(private val context: Context) : MPVLib.EventObserver {
|
||||
MPVLib.setPropertyDouble("panscan", panscanValue)
|
||||
}
|
||||
|
||||
// MARK: - Technical Info
|
||||
|
||||
fun getTechnicalInfo(): Map<String, Any> {
|
||||
val info = mutableMapOf<String, Any>()
|
||||
|
||||
// Video dimensions
|
||||
MPVLib.getPropertyInt("video-params/w")?.takeIf { it > 0 }?.let {
|
||||
info["videoWidth"] = it
|
||||
}
|
||||
MPVLib.getPropertyInt("video-params/h")?.takeIf { it > 0 }?.let {
|
||||
info["videoHeight"] = it
|
||||
}
|
||||
|
||||
// Video codec
|
||||
MPVLib.getPropertyString("video-format")?.let {
|
||||
info["videoCodec"] = it
|
||||
}
|
||||
|
||||
// Audio codec
|
||||
MPVLib.getPropertyString("audio-codec-name")?.let {
|
||||
info["audioCodec"] = it
|
||||
}
|
||||
|
||||
// FPS (container fps)
|
||||
MPVLib.getPropertyDouble("container-fps")?.takeIf { it > 0 }?.let {
|
||||
info["fps"] = it
|
||||
}
|
||||
|
||||
// Video bitrate (bits per second)
|
||||
MPVLib.getPropertyInt("video-bitrate")?.takeIf { it > 0 }?.let {
|
||||
info["videoBitrate"] = it
|
||||
}
|
||||
|
||||
// Audio bitrate (bits per second)
|
||||
MPVLib.getPropertyInt("audio-bitrate")?.takeIf { it > 0 }?.let {
|
||||
info["audioBitrate"] = it
|
||||
}
|
||||
|
||||
// Demuxer cache duration (seconds of video buffered)
|
||||
MPVLib.getPropertyDouble("demuxer-cache-duration")?.let {
|
||||
info["cacheSeconds"] = it
|
||||
}
|
||||
|
||||
// Dropped frames
|
||||
MPVLib.getPropertyInt("frame-drop-count")?.let {
|
||||
info["droppedFrames"] = it
|
||||
}
|
||||
|
||||
return info
|
||||
}
|
||||
|
||||
// MARK: - MPVLib.EventObserver
|
||||
|
||||
override fun eventProperty(property: String) {
|
||||
|
||||
@@ -173,6 +173,11 @@ class MpvPlayerModule : Module() {
|
||||
view.isZoomedToFill()
|
||||
}
|
||||
|
||||
// Technical info function
|
||||
AsyncFunction("getTechnicalInfo") { view: MpvPlayerView ->
|
||||
view.getTechnicalInfo()
|
||||
}
|
||||
|
||||
// Defines events that the view can send to JavaScript
|
||||
Events("onLoad", "onPlaybackStateChange", "onProgress", "onError", "onTracksReady")
|
||||
}
|
||||
|
||||
@@ -330,6 +330,12 @@ class MpvPlayerView(context: Context, appContext: AppContext) : ExpoView(context
|
||||
return _isZoomedToFill
|
||||
}
|
||||
|
||||
// MARK: - Technical Info
|
||||
|
||||
fun getTechnicalInfo(): Map<String, Any> {
|
||||
return renderer?.getTechnicalInfo() ?: emptyMap()
|
||||
}
|
||||
|
||||
// MARK: - MPVLayerRenderer.Delegate
|
||||
|
||||
override fun onPositionChanged(position: Double, duration: Double) {
|
||||
|
||||
@@ -763,4 +763,64 @@ final class MPVLayerRenderer {
|
||||
getProperty(handle: handle, name: "aid", format: MPV_FORMAT_INT64, value: &aid)
|
||||
return Int(aid)
|
||||
}
|
||||
|
||||
// MARK: - Technical Info
|
||||
|
||||
func getTechnicalInfo() -> [String: Any] {
|
||||
guard let handle = mpv else { return [:] }
|
||||
|
||||
var info: [String: Any] = [:]
|
||||
|
||||
// Video dimensions
|
||||
var videoWidth: Int64 = 0
|
||||
var videoHeight: Int64 = 0
|
||||
if getProperty(handle: handle, name: "video-params/w", format: MPV_FORMAT_INT64, value: &videoWidth) >= 0 {
|
||||
info["videoWidth"] = Int(videoWidth)
|
||||
}
|
||||
if getProperty(handle: handle, name: "video-params/h", format: MPV_FORMAT_INT64, value: &videoHeight) >= 0 {
|
||||
info["videoHeight"] = Int(videoHeight)
|
||||
}
|
||||
|
||||
// Video codec
|
||||
if let videoCodec = getStringProperty(handle: handle, name: "video-format") {
|
||||
info["videoCodec"] = videoCodec
|
||||
}
|
||||
|
||||
// Audio codec
|
||||
if let audioCodec = getStringProperty(handle: handle, name: "audio-codec-name") {
|
||||
info["audioCodec"] = audioCodec
|
||||
}
|
||||
|
||||
// FPS (container fps)
|
||||
var fps: Double = 0
|
||||
if getProperty(handle: handle, name: "container-fps", format: MPV_FORMAT_DOUBLE, value: &fps) >= 0 && fps > 0 {
|
||||
info["fps"] = fps
|
||||
}
|
||||
|
||||
// Video bitrate (bits per second)
|
||||
var videoBitrate: Int64 = 0
|
||||
if getProperty(handle: handle, name: "video-bitrate", format: MPV_FORMAT_INT64, value: &videoBitrate) >= 0 && videoBitrate > 0 {
|
||||
info["videoBitrate"] = Int(videoBitrate)
|
||||
}
|
||||
|
||||
// Audio bitrate (bits per second)
|
||||
var audioBitrate: Int64 = 0
|
||||
if getProperty(handle: handle, name: "audio-bitrate", format: MPV_FORMAT_INT64, value: &audioBitrate) >= 0 && audioBitrate > 0 {
|
||||
info["audioBitrate"] = Int(audioBitrate)
|
||||
}
|
||||
|
||||
// Demuxer cache duration (seconds of video buffered)
|
||||
var cacheSeconds: Double = 0
|
||||
if getProperty(handle: handle, name: "demuxer-cache-duration", format: MPV_FORMAT_DOUBLE, value: &cacheSeconds) >= 0 {
|
||||
info["cacheSeconds"] = cacheSeconds
|
||||
}
|
||||
|
||||
// Dropped frames
|
||||
var droppedFrames: Int64 = 0
|
||||
if getProperty(handle: handle, name: "frame-drop-count", format: MPV_FORMAT_INT64, value: &droppedFrames) >= 0 {
|
||||
info["droppedFrames"] = Int(droppedFrames)
|
||||
}
|
||||
|
||||
return info
|
||||
}
|
||||
}
|
||||
|
||||
@@ -173,6 +173,11 @@ public class MpvPlayerModule: Module {
|
||||
return view.isZoomedToFill()
|
||||
}
|
||||
|
||||
// Technical info function
|
||||
AsyncFunction("getTechnicalInfo") { (view: MpvPlayerView) -> [String: Any] in
|
||||
return view.getTechnicalInfo()
|
||||
}
|
||||
|
||||
// Defines events that the view can send to JavaScript
|
||||
Events("onLoad", "onPlaybackStateChange", "onProgress", "onError", "onTracksReady")
|
||||
}
|
||||
|
||||
@@ -282,6 +282,12 @@ class MpvPlayerView: ExpoView {
|
||||
return _isZoomedToFill
|
||||
}
|
||||
|
||||
// MARK: - Technical Info
|
||||
|
||||
func getTechnicalInfo() -> [String: Any] {
|
||||
return renderer?.getTechnicalInfo() ?? [:]
|
||||
}
|
||||
|
||||
deinit {
|
||||
pipController?.stopPictureInPicture()
|
||||
renderer?.stop()
|
||||
|
||||
@@ -89,6 +89,8 @@ export interface MpvPlayerViewRef {
|
||||
// Video scaling
|
||||
setZoomedToFill: (zoomed: boolean) => Promise<void>;
|
||||
isZoomedToFill: () => Promise<boolean>;
|
||||
// Technical info
|
||||
getTechnicalInfo: () => Promise<TechnicalInfo>;
|
||||
}
|
||||
|
||||
export type SubtitleTrack = {
|
||||
@@ -106,3 +108,15 @@ export type AudioTrack = {
|
||||
channels?: number;
|
||||
selected?: boolean;
|
||||
};
|
||||
|
||||
export type TechnicalInfo = {
|
||||
videoWidth?: number;
|
||||
videoHeight?: number;
|
||||
videoCodec?: string;
|
||||
audioCodec?: string;
|
||||
fps?: number;
|
||||
videoBitrate?: number;
|
||||
audioBitrate?: number;
|
||||
cacheSeconds?: number;
|
||||
droppedFrames?: number;
|
||||
};
|
||||
|
||||
@@ -101,6 +101,10 @@ export default React.forwardRef<MpvPlayerViewRef, MpvPlayerViewProps>(
|
||||
isZoomedToFill: async () => {
|
||||
return await nativeRef.current?.isZoomedToFill();
|
||||
},
|
||||
// Technical info
|
||||
getTechnicalInfo: async () => {
|
||||
return await nativeRef.current?.getTechnicalInfo();
|
||||
},
|
||||
}));
|
||||
|
||||
return <NativeView ref={nativeRef} {...props} />;
|
||||
|
||||
Reference in New Issue
Block a user