SRGSSR / pillarbox-apple

A next-generation reactive media playback ecosystem for Apple platforms.
https://testflight.apple.com/join/TS6ngLqf
MIT License
58 stars 9 forks source link

SystemVideoView doesn't show controls #806

Closed hoschiho closed 6 months ago

hoschiho commented 7 months ago

Description of the problem

Using the SystemVideoView instead of VideoView, doesn't display the iOS specific default controls.

I was able to display them, by adding controller.beginAppearanceTransition(true, animated: false) in BasicSystemVideoView.swift:


import AVKit
import SwiftUI
import PillarboxPlayer

struct MyBasicSystemVideoView: UIViewControllerRepresentable {
    let player: Player
    let gravity: AVLayerVideoGravity

#if os(tvOS)
    func makeCoordinator() -> AVPlayerViewControllerSpeedCoordinator {
        .init()
    }
#endif

    func makeUIViewController(context: Context) -> AVPlayerViewController {
        let controller = AVPlayerViewController()
        controller.beginAppearanceTransition(true, animated: false)
        controller.allowsPictureInPicturePlayback = false
#if os(tvOS)
        controller.playbackControlsIncludeInfoViews = true
#endif
        return controller
    }

    func updateUIViewController(_ uiViewController: AVPlayerViewController, context: Context) {
        uiViewController.player = player.systemPlayer
        uiViewController.videoGravity = gravity
#if os(tvOS)
        context.coordinator.player = player
        context.coordinator.controller = uiViewController
#endif
    }
}

source: https://forums.developer.apple.com/forums/thread/711360?wt_debug=1&wtstp_debug=1

Relevant stack trace or log output

No response

Reproducibility

Always

Steps to reproduce

Using SystemVideoView instead of VideoView

Library version

1.0.1

Operating system

ios 17

Code sample

No response

Is there an existing issue for this?

defagos commented 7 months ago

Hi,

Thanks for your issue report and sorry for the delay.

Do you mean that system player controls are never displayed and can never be toggled on again? If yes, do you have a small code sample reproducing the problem (because we never experienced it in practice) or could you provide us with some insights about how the SystemVideoView was embedded into your view hierarchy so that we can try to reproduce it on our side?

Thank you very much in advance for your help.

hoschiho commented 7 months ago

Hello @defagos Yes, the system player controls are never displayed and can't be toggled. What's interesting, once I use the SystemVideoView, I can play & pause the video by clicking in the middle (where usually the play button would be), without any visual feedback.

We're using a UIHostingController to display the SwiftUI view:

import Foundation
import Flutter
import UIKit
import SwiftUI
import PillarboxPlayer

class FLNativeView: NSObject, FlutterPlatformView {
    private var _view: UIView

    init(
        frame: CGRect,
        viewIdentifier viewId: Int64,
        arguments args: Any?,
        binaryMessenger messenger: FlutterBinaryMessenger?,
        playerWrapper: PlayerWrapper
    ) {
        _view = UIView()
        super.init()
        let childView = UIHostingController(rootView: VideoPlayerView(playerWrapper: playerWrapper))
        childView.view.frame = frame
        _view.addConstrained(subview: childView.view)
        childView.didMove(toParent:_view.inputViewController)

    }

    func view() -> UIView {
        return _view
    }
}

extension UIView {
    func addConstrained(subview: UIView) {
        addSubview(subview)
        subview.translatesAutoresizingMaskIntoConstraints = false
        subview.topAnchor.constraint(equalTo: topAnchor).isActive = true
        subview.leadingAnchor.constraint(equalTo: leadingAnchor).isActive = true
        subview.trailingAnchor.constraint(equalTo: trailingAnchor).isActive = true
        subview.bottomAnchor.constraint(equalTo: bottomAnchor).isActive = true
    }
}

And the VideoPlayerView is just the SystemVideoView:

var body: some View {
        SystemVideoView(player: playerWrapper.player)
    }

I hope this helps.

defagos commented 7 months ago

Thanks for the information, we'll have a look with UIHostingController involved.

defagos commented 7 months ago

I implemented the following scenarios with a custom PlayerView embedding SystemVideoView and an associated player:

In all these use cases the behavior is fine.

I then applied the fix suggested in the link you provide. This breaks Picture in Picture automatic restoration on tvOS, though, in the following case:

We'll investigate further but it might be helpful if we can build, run and debug your project. This way we can avoid introducing a fix that may do more harm than good.

defagos commented 7 months ago

Looking at your code it feels strange that inputViewController is involved as parent controller since this controller is related to keyboard input (active responder). See associated documentation.

Parent-child containment relationships are very important for correct view lifecycle propagation. Maybe this is what explains the issue your observe, or maybe Flutter does not maintain correct containment relationships somewjere.

If you can provide us with either access to your code, or to a small example reproducing this issue in Flutter (we don't know how you integrate Pilllarbox so we are a bit in the dark), we would be able to better investigate view and controller hierarchies to discover what might be misssing, either in your implementation or in Flutter.

If you prefer we can also attempt to debug your code together.

Thanks in advance for your help.

waliid commented 6 months ago

Hi @hoschiho,

First, thank you for providing us access to your code.

So, after some investigations, we have found a solution to use directly the Pillarbox SystemVideoView instead of reinventing the wheel with an UIViewControllerRepresentable and adding a specific behavior such as calling beginAppearanceTransition(_:animated:). Hence, instead of using MyBasicSystemVideoView we are now able to use SystemVideoView in the VideoPlayerView.

I've tried to improve some part of code related to the playback, and I also allowed myself to create a PR with some improvements in my point of view.

waliid commented 6 months ago

Fixed.