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

This commit is contained in:
Fredrik Burmester
2026-01-13 22:43:05 +01:00
22 changed files with 2358 additions and 15 deletions

View File

@@ -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
}
}

View File

@@ -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")
}

View File

@@ -282,6 +282,12 @@ class MpvPlayerView: ExpoView {
return _isZoomedToFill
}
// MARK: - Technical Info
func getTechnicalInfo() -> [String: Any] {
return renderer?.getTechnicalInfo() ?? [:]
}
deinit {
pipController?.stopPictureInPicture()
renderer?.stop()