Проблема заключается в том, что В первый раз я открываю поток (после запуска приложения), соотношение аспекта не применяется . Видео растягивается неправильно (обычно заполняет контейнер, игнорируя его родной аспект). Во второй раз видео обычно регулируется правильно. Но это не всегда стреляет во времени при первом забеге, или регулировка игнорируется.
вещи, которые я уже пробовал:
- Настройка Player.scalefactor = 0.0 и Player.videAspectratio = Nil Promant. videoAspectRatio manually in mediaPlayerStateChanged
- Delaying with DispatchQueue.main.asyncAfter(...)
- Ensuring drawable view is fully laid out
- Setting autoresizingMask and clipsToBounds Правильно < /li>
< /ul>
Мой вопрос: < /h3>
Как я могу надежно применять видеоаптрин, чтобы видео никогда не растягивается - не только при первом воспроизведении потока, но и каждый раз, когда поток начинается? Может ли это быть условием гонки или проблемы с временем внутри vlcmediaPlayer? < /P>
Любые идеи или лучшие практики? 3.3.16.3 - Воспроизведение RTSP-потока из камеры Reolink
https://imgur.com/a/eqncumu> PrettyPrint-Override ">import Foundation
import Capacitor
import MobileVLCKit
@objc(RtspVlcPlugin)
public class RtspVlcPlugin: CAPPlugin, CAPBridgedPlugin, VLCMediaPlayerDelegate {
public let identifier = "RtspVlcPlugin"
public let jsName = "RtspVlcPlugin"
public let pluginMethods: [CAPPluginMethod] = [
CAPPluginMethod(name: "start", returnType: CAPPluginReturnPromise),
CAPPluginMethod(name: "stop", returnType: CAPPluginReturnPromise),
CAPPluginMethod(name: "show", returnType: CAPPluginReturnPromise),
CAPPluginMethod(name: "hide", returnType: CAPPluginReturnPromise)
]
private var mediaPlayer: VLCMediaPlayer?
private var containerView: UIView?
private var spinner: UIActivityIndicatorView?
private var hasAdjustedVideo = false
override public func load() {
print("
}
@objc func start(_ call: CAPPluginCall) {
guard let urlStr = call.getString("url"),
let x = call.getDouble("x"),
let y = call.getDouble("y"),
let w = call.getDouble("width"),
let h = call.getDouble("height"),
let url = URL(string: urlStr) else {
call.reject("Invalid parameters")
return
}
DispatchQueue.main.async {
let scale = UIScreen.main.scale
let ax = x / scale, ay = y / scale
let aw = w / scale, ah = h / scale
self.containerView?.removeFromSuperview()
guard let webView = self.bridge?.webView,
let superview = webView.superview else {
call.reject("WebView not available")
return
}
let container = UIView(frame: CGRect(x: ax, y: ay, width: aw, height: ah))
container.backgroundColor = .black
container.layer.cornerRadius = 16
container.clipsToBounds = true
let videoView = UIView(frame: container.bounds)
videoView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
videoView.contentMode = .scaleToFill
videoView.clipsToBounds = true
container.addSubview(videoView)
let spinner = UIActivityIndicatorView(style: .large)
spinner.center = CGPoint(x: aw / 2, y: ah / 2)
spinner.color = .white
spinner.startAnimating()
container.addSubview(spinner)
self.containerView = container
self.spinner = spinner
superview.addSubview(container)
let media = VLCMedia(url: url)
media.addOptions([
"--rtsp-tcp": true,
"--network-caching": 1000,
"--file-caching": 1000,
"--live-caching": 1000,
"--clock-jitter": 0,
"--clock-synchro": 0,
"--udp-buffer": 524288
])
let player = VLCMediaPlayer()
player.delegate = self
player.drawable = videoView
player.media = media
player.scaleFactor = 0.0
player.videoAspectRatio = nil
self.mediaPlayer = player
self.hasAdjustedVideo = false
player.play()
call.resolve()
}
}
@objc func stop(_ call: CAPPluginCall) {
print("
DispatchQueue.main.async {
self.mediaPlayer?.stop()
self.mediaPlayer = nil
self.spinner?.stopAnimating()
self.spinner?.removeFromSuperview()
self.spinner = nil
self.containerView?.removeFromSuperview()
self.containerView = nil
self.hasAdjustedVideo = false
call.resolve()
}
}
@objc func hide(_ call: CAPPluginCall) {
print("
DispatchQueue.main.async {
self.containerView?.isHidden = true
call.resolve()
}
}
@objc func show(_ call: CAPPluginCall) {
print("👁 RtspVlcPlugin → show called")
DispatchQueue.main.async {
self.containerView?.isHidden = false
call.resolve()
}
}
public func mediaPlayerStateChanged(_ notification: Notification!) {
guard let player = mediaPlayer else { return }
if player.state == .playing && !hasAdjustedVideo {
print("
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
self.applyAspectRatio()
}
}
}
private func applyAspectRatio() {
guard let player = mediaPlayer,
let container = self.containerView else { return }
DispatchQueue.main.async {
self.spinner?.stopAnimating()
self.spinner?.removeFromSuperview()
self.spinner = nil
player.scaleFactor = 0.0
let w = Int(container.frame.width)
let h = Int(container.frame.height)
let aspect = "\(w):\(h)"
print("
aspect.withCString { cStr in
player.videoAspectRatio = UnsafeMutablePointer(mutating: cStr)
}
self.hasAdjustedVideo = true
}
}
}
Подробнее здесь: https://stackoverflow.com/questions/796 ... -videoaspe
Мобильная версия