hi
I am having a issue with sound on a network video stream, the stream is loaded by a m3u,. during playback there is no audio from the device, however when using headphones / airplay audio works correctly.
the other peculiar thing is the device simulator works fine. this maybe related to airplay working, but I don't know.
this is the view handling the playback. Im not sure where the issue is. I can also play the videos fine when embedding the avplayer in its own view. but that looks messy when you have to dismiss a second window when closing the video.
#if os(iOS)
import SwiftUI
import AVKit
import MediaPlayer
struct iOSVideoLibraryView: View {
@ObservedObject var videoLibrary: VideoLibrary
@State private var isPlayerDismissed = false
let LiveStreams = [GridItem(.flexible()), GridItem(.flexible()), GridItem(.flexible())]
let VODStreams = [GridItem(.flexible()), GridItem(.flexible()), GridItem(.flexible()), GridItem(.flexible())]
var body: some View {
NavigationView {
ScrollView {
LazyVGrid(columns: LiveStreams, spacing: 20) {
ForEach(videoLibrary.videos, id: \.title) { video in
if video.type == "LIVE" {
Button(action: {
isPlayerDismissed = false // Reset the dismissal flag
presentVideoPlayer(videoURL: video.referenceURL)
}) {
VStack {
Image(systemName: "play.circle.fill")
.font(.system(size: 30)) // icon
.foregroundColor(.blue)
Text(video.title)
.frame(width: 100, height: 50) // title bounds
.font(Font.caption)
.background(Color.blue)
.foregroundColor(.white)
.cornerRadius(3)
}
.frame(width: 70) // main button container
.padding()
.background(Color.blue.opacity(0.2))
.cornerRadius(10)
}
} else {
// Handle non-LIVE videos
}
}
}
.padding()
}
.navigationBarTitle("Live Streams")
}
}
private func presentVideoPlayer(videoURL: URL) {
let playerViewController = CustomAVPlayerViewController()
let player = AVPlayer(url: videoURL)
playerViewController.player = player
player.isMuted = false
player.play()
DispatchQueue.main.async {
playerViewController.modalPresentationStyle = .fullScreen
UIApplication.shared.windows.first?.rootViewController?.present(playerViewController, animated: true, completion: nil)
}
}
}
class PlayerManager: NSObject, AVPictureInPictureControllerDelegate {
static let shared = PlayerManager()
func pictureInPictureControllerWillStartPictureInPicture(_ pictureInPictureController: AVPictureInPictureController) {
// Perform any necessary actions when picture-in-picture starts
}
func pictureInPictureControllerDidStopPictureInPicture(_ pictureInPictureController: AVPictureInPictureController) {
// Perform any necessary actions when picture-in-picture stops
}
func pictureInPictureController(_ pictureInPictureController: AVPictureInPictureController, failedToStartPictureInPictureWithError error: Error) {
// Perform any necessary actions when picture-in-picture fails to start
}
}
class CustomAVPlayerViewController: AVPlayerViewController {
let playerManager = PlayerManager.shared
let customPlayer = AVPlayer()
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
if AVPictureInPictureController.isPictureInPictureSupported() {
if let playerItem = customPlayer.currentItem {
let playerLayer = AVPlayerLayer(player: customPlayer)
playerLayer.videoGravity = .resizeAspectFill
let pictureInPictureController = AVPictureInPictureController(playerLayer: playerLayer)
pictureInPictureController?.delegate = playerManager
if let pictureInPictureController = pictureInPictureController,
pictureInPictureController.isPictureInPicturePossible {
pictureInPictureController.startPictureInPicture()
}
}
}
}
override func viewDidLoad() {
super.viewDidLoad()
customPlayer.addObserver(self, forKeyPath: "currentItem", options: .new, context: nil)
}
override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)
customPlayer.removeObserver(self, forKeyPath: "currentItem")
}
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
if keyPath == "currentItem" {
if let playerItem = customPlayer.currentItem {
// Handle player item change
}
}
}
}
#endif