Hi Team,
We see an issue with this version if CoreMedia requesting multiple qualities at all times for a stream. We don't see this issue on 1.0.0.21C62. We are unsure what would be causing this.
[2024-01-05 16:53:51] "GET /live/cinecanal/live/cinecanal_720p/video.m3u8?_HLS_msn=630&_HLS_part=0 HTTP/1.0" 200 1145 2529 1090199 "-" "AppleCoreMedia/1.0.0.21B101 (iPhone; U; CPU OS 17_1_2 like Mac OS X; en_us)"
[2024-01-05 16:53:52] "GET /live/cinecanal/live/cinecanal_1080p/audio.m3u8?_HLS_msn=630&_HLS_part=0 HTTP/1.0" 200 1146 2396 1013356 "-" "AppleCoreMedia/1.0.0.21B101 (iPhone; U; CPU OS 17_1_2 like Mac OS X; en_us)"
[2024-01-05 16:53:52] "GET /live/cinecanal/live/cinecanal_1080p/a_1459_2452140264_630_0.fmp4 HTTP/1.0" 200 1139 24975 1013385 "-" "AppleCoreMedia/1.0.0.21B101 (iPhone; U; CPU OS 17_1_2 like Mac OS X; en_us)"
[2024-01-05 16:53:52] "GET /live/cinecanal/live/cinecanal_720p/video.m3u8?_HLS_msn=630&_HLS_part=1 HTTP/1.0" 200 1145 2603 998670 "-" "AppleCoreMedia/1.0.0.21B101 (iPhone; U; CPU OS 17_1_2 like Mac OS X; en_us)"
[2024-01-05 16:53:52] "GET /live/cinecanal/live/cinecanal_720p/v_1058_2452140000_630_1.fmp4 HTTP/1.0" 200 1138 40534 998739 "-" "AppleCoreMedia/1.0.0.21B101 (iPhone; U; CPU OS 17_1_2 like Mac OS X; en_us)"
[2024-01-05 16:53:53] "GET /live/cinecanal/live/cinecanal_720p/video.m3u8?_HLS_msn=630&_HLS_part=2 HTTP/1.0" 200 1145 2677 835327 "-" "AppleCoreMedia/1.0.0.21B101 (iPhone; U; CPU OS 17_1_2 like Mac OS X; en_us)"
[2024-01-05 16:53:53] "GET /live/cinecanal/live/cinecanal_720p/v_1058_2452140000_630_2.fmp4 HTTP/1.0" 200 1138 57656 835207 "-" "AppleCoreMedia/1.0.0.21B101 (iPhone; U; CPU OS 17_1_2 like Mac OS X; en_us)"
[2024-01-05 16:53:53] "GET /live/cinecanal/live/cinecanal_1080p/audio.m3u8?_HLS_msn=630&_HLS_part=1 HTTP/1.0" 200 1146 2458 986038 "-" "AppleCoreMedia/1.0.0.21B101 (iPhone; U; CPU OS 17_1_2 like Mac OS X; en_us)"
[2024-01-05 16:53:53] "GET /live/cinecanal/live/cinecanal_1080p/a_1459_2452140264_630_1.fmp4 HTTP/1.0" 200 1139 24700 986032 "-" "AppleCoreMedia/1.0.0.21B101 (iPhone; U; CPU OS 17_1_2 like Mac OS X; en_us)"
[2024-01-05 16:53:54] "GET /live/cinecanal/live/cinecanal_720p/video.m3u8?_HLS_msn=630&_HLS_part=3 HTTP/1.0" 200 1145 2751 1013257 "-" "AppleCoreMedia/1.0.0.21B101 (iPhone; U; CPU OS 17_1_2 like Mac OS X; en_us)"
[2024-01-05 16:53:54] "GET /live/cinecanal/live/cinecanal_720p/v_1058_2452140000_630_3.fmp4 HTTP/1.0" 200 1138 55900 1013324 "-" "AppleCoreMedia/1.0.0.21B101 (iPhone; U; CPU OS 17_1_2 like Mac OS X; en_us)"
[2024-01-05 16:53:54] "GET /live/cinecanal/live/cinecanal_1080p/audio.m3u8?_HLS_msn=630&_HLS_part=2 HTTP/1.0" 200 1146 2520 1016693 "-" "AppleCoreMedia/1.0.0.21B101 (iPhone; U; CPU OS 17_1_2 like Mac OS X; en_us)"
[2024-01-05 16:53:54] "GET /live/cinecanal/live/cinecanal_1080p/a_1459_2452140264_630_2.fmp4 HTTP/1.0" 200 1139 25014 1016717 "-" "AppleCoreMedia/1.0.0.21B101 (iPhone; U; CPU OS 17_1_2 like Mac OS X; en_us)"
[2024-01-05 16:53:55] "GET /live/cinecanal/live/cinecanal_720p/video.m3u8?_HLS_msn=630&_HLS_part=4 HTTP/1.0" 200 1145 2825 917753 "-" "AppleCoreMedia/1.0.0.21B101 (iPhone; U; CPU OS 17_1_2 like Mac OS X; en_us)"
[2024-01-05 16:53:55] "GET /live/cinecanal/live/cinecanal_720p/v_1058_2452140000_630_4.fmp4 HTTP/1.0" 200 1138 103745 917903 "-" "AppleCoreMedia/1.0.0.21B101 (iPhone; U; CPU OS 17_1_2 like Mac OS X; en_us)"
[2024-01-05 16:53:55] "GET /live/cinecanal/live/cinecanal_1080p/audio.m3u8?_HLS_msn=630&_HLS_part=3 HTTP/1.0" 200 1146 2582 958102 "-" "AppleCoreMedia/1.0.0.21B101 (iPhone; U; CPU OS 17_1_2 like Mac OS X; en_us)"
[2024-01-05 16:53:55] "GET /live/cinecanal/live/cinecanal_1080p/a_1459_2452140264_630_3.fmp4 HTTP/1.0" 200 1139 24782 958195 "-" "AppleCoreMedia/1.0.0.21B101 (iPhone; U; CPU OS 17_1_2 like Mac OS X; en_us)"
[2024-01-05 16:53:56] "GET /live/cinecanal/live/cinecanal_720p/video.m3u8?_HLS_msn=630&_HLS_part=5 HTTP/1.0" 200 1145 2899 931101 "-" "AppleCoreMedia/1.0.0.21B101 (iPhone; U; CPU OS 17_1_2 like Mac OS X; en_us)"
[2024-01-05 16:53:56] "GET /live/cinecanal/live/cinecanal_720p/v_1058_2452140000_630_5.fmp4 HTTP/1.0" 200 1138 112113 931228 "-" "AppleCoreMedia/1.0.0.21B101 (iPhone; U; CPU OS 17_1_2 like Mac OS X; en_us)"
[2024-01-05 16:53:56] "GET /live/cinecanal/live/cinecanal_1080p/audio.m3u8?_HLS_msn=630&_HLS_part=4 HTTP/1.0" 200 1146 2644 935550 "-" "AppleCoreMedia/1.0.0.21B101 (iPhone; U; CPU OS 17_1_2 like Mac OS X; en_us)"
[2024-01-05 16:53:56] "GET /live/cinecanal/live/cinecanal_1080p/a_1459_2452140264_630_4.fmp4 HTTP/1.0" 200 1139 24824 937720 "-" "AppleCoreMedia/1.0.0.21B101 (iPhone; U; CPU OS 17_1_2 like Mac OS X; en_us)"
[2024-01-05 16:53:57] "GET /live/cinecanal/live/cinecanal_1080p/audio.m3u8?_HLS_msn=630&_HLS_part=5 HTTP/1.0" 200 1146 2706 895680 "-" "AppleCoreMedia/1.0.0.21B101 (iPhone; U; CPU OS 17_1_2 like Mac OS X; en_us)"
[2024-01-05 16:53:57] "GET /live/cinecanal/live/cinecanal_1080p/a_1459_2452140264_630_5.fmp4 HTTP/1.0" 200 1139 24843 895734 "-" "AppleCoreMedia/1.0.0.21B101 (iPhone; U; CPU OS 17_1_2 like Mac OS X; en_us)"
[2024-01-05 16:53:57] "GET /live/cinecanal/live/cinecanal_720p/video.m3u8?_HLS_msn=631&_HLS_part=0 HTTP/1.0" 200 1145 2529 907045 "-" "AppleCoreMedia/1.0.0.21B101 (iPhone; U; CPU OS 17_1_2 like Mac OS X; en_us)"
AVKit
RSS for tagCreate view-level services for media playback, complete with user controls, chapter navigation, and support for subtitles and closed captioning using AVKit.
Posts under AVKit tag
74 Posts
Sort by:
Post
Replies
Boosts
Views
Activity
The following type of problem has appeared. I need to flip through the video. Imagine you have, say, 3 videos, and you can scroll through them and choose which video you want to watch.
For this, I decided to use a TabView with the .page style. But it turned out that it didn't work. And I found myself in a stupor.
The TabView itself starts to lag, the scrolling starts to lag, the videos do not start the first time, and sometimes the control panel does not even appear on some videos, which is why it is impossible to expand the video to full screen.
The code will be below, maybe someone has encountered this problem, how did he solve it, maybe there are some other options to make a similar logic?
let videos: [String] = ["burpee", "squat", "step-up", "sun-salute"]
var body: some View {
TabView {
ForEach(videos, id: \.self) { videoName in
VideoPlayerView(videoName: videoName)
.clipShape(RoundedRectangle(cornerRadius: 25))
}
}
.frame(width: 375, height: 230)
}
struct VideoPlayerView: View {
let videoName: String
var body: some View {
if let videoURL = Bundle.main.url(forResource: videoName, withExtension: "mp4") {
VideoPlayerWrapper(player: AVPlayer(url: videoURL))
} else {
Text("No Video \(videoName)")
}
}
}
#Preview {
VideoPlayerView(videoName: "squat")
}
struct VideoPlayerWrapper: UIViewControllerRepresentable {
let player: AVPlayer
func makeUIViewController(context: Context) -> AVPlayerViewController {
let controller = AVPlayerViewController()
controller.player = player
controller.showsPlaybackControls = true
return controller
}
func updateUIViewController(_ uiViewController: AVPlayerViewController, context: Context) {}
}
Crash seems to be in a private Apple framework. There's some other reports of this floating around but no solutions so far. Any ideas?
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[WebAVPlayerLayer startRedirectingVideoToLayer:forMode:]: unrecognized selector sent to instance 0x6000037033c0'
*** First throw call stack:
(
0 CoreFoundation 0x0000000187d56800 __exceptionPreprocess + 176
1 libobjc.A.dylib 0x000000018784deb4 objc_exception_throw + 60
2 CoreFoundation 0x0000000187e083bc -[NSObject(NSObject) __retain_OA] + 0
3 CoreFoundation 0x0000000187cc0a84 forwarding + 1572
4 CoreFoundation 0x0000000187cc03a0 _CF_forwarding_prep_0 + 96
5 AVKit 0x00000001bdc81f30 -[__AVPlayerLayerView startRoutingVideoToPictureInPicturePlayerLayerView] + 156
6 AVKit 0x00000001bdcf1d48 -[AVPictureInPicturePlatformAdapter(Common) _setRoutingVideoToHostedWindow:pictureInPictureViewController:source:] + 84
7 AVKit 0x00000001bdcd952c -[AVPictureInPicturePlatformAdapter startPictureInPicture] + 380
8 AVKit 0x000000022883000c -[AVPictureInPicturePlatformAdapterAccessibility startPictureInPicture] + 44
9 AVKit 0x00000001bdcddea0 -[AVPictureInPictureController startPictureInPicture] + 216
10 WebCore 0x00000001c75277c8 -[WebAVPlayerViewController startPictureInPicture] + 128
11 libdispatch.dylib 0x0000000102c64f14 _dispatch_call_block_and_release + 32
I'm creating an app with a video player streaming video from an URL. The AVPlayer only takes the URL address of the video but I'd like to create a custom URLRequest and then use that to stream the video from online.
So current situation is this:
let videourl = URL(string: "videofoobar.com")
let player = AVPlayer(url: videourl)
player.play()
And I would like to go to something like this:
let videourl = URL(string: "videofoobar.com")
var request = URLRequest(url: videourl)
let player = AVPlayer(request: request) //This obviously fails, any workaround?
player.play()
I know it is not possible to do it like this as AVPlayer only takes URL or AVPlayerItem as parameter. Is there any workaround to make URLRequest and then give it to AVPlayer for online streaming?
On macOS Sonoma I have a SwiftUI app that correctly plays remote video files and local video files from the app bundle.
Where I'm having trouble is setting up the AVPlayer URL for a UVC camera device directly connected on the Mac.
let url = URL(string: "https://some-remote-video.mp4")!
player = AVPlayer(url: url)
player.play()
Is there some magic to using a UVC device with AVPlayer, or do I need to access the UVC device differently?
Thanks,
Grahm
I’ve got some code that creates an AVPlayerItem from a URL, the creates an AVQueuePlayer from it. If I check the player item's status after that, it's still unknown.
According to the docs, it'll remain unknown until it is associated with an AVPlayer, and then it "immediately begins enqueuing the item’s media and preparing it for playback." But checking the status right after that, I still get unknown, which tells me it’s not quite immediate.
Is there any way to test if the player item will work immediately after creation? In this case, the problem is that my app doesn't have permission, due to it being a bookmark saved in a sandboxed app.
In my SwiftUI/SwiftData application, I want to store videos in SwiftData objects (using external storage). To display them, I need to instantiate an AVPlayer (for use in a VideoPlayer view). But AVPlayer expects a URL, not a Data object.
Obviously, I can solve this problem via a file-caching scheme (i.e., by creating a local file when needed, using an LRU cache to control it's lifetime), but this results in an extra copy of the data (besides the hidden local file managed by SwiftData/CoreData). However, since videos can be quite large, I would prefer not to do that.
Has anyone any thoughts about how I can avoid the extra data copy?
Is there a way to play a specific rectangular region of interest of a video in an arbitrarily-sized view?
Let's say I have a 1080p video but I'm only interested in a sub-region of the full frame. Is there a way to specify a source rect to be displayed in an arbitrary view (SwiftUI view, ideally), and have it play that in real time, without having to pre-render the cropped region?
Update: I may have found a solution here: img DOT ly/blog/trim-and-crop-video-in-swift/ (Apple won't allow that URL for some dumb reason)
Hi, I'm trying to play multiple video/audio file with AVPlayer using AVMutableComposition. Each video/audio file can process simultaneously so I set each video/audio in individual tracks. I use only local file.
let second = CMTime(seconds: 1, preferredTimescale: 1000)
let duration = CMTimeRange(start: .zero, duration: second)
var currentTime = CMTime.zero
for _ in 0...4 {
let mutableTrack = composition.addMutableTrack(
withMediaType: .audio,
preferredTrackID: kCMPersistentTrackID_Invalid
)
try mutableTrack?.insertTimeRange(
duration,
of: audioAssetTrack,
at: currentTime
)
currentTime = currentTime + second
}
When I set many audio tracks (maybe more than 5), the first part sounds a little different from original when it starts. It seems like audio's front part is skipped.
But when I set only two tracks, AVPlayer plays as same as original file.
avPlayer.play()
How can I fix it? Why do audio tracks affect that don't have any playing parts when start? Please let me know.
Hi,
I've started learning swiftUI a few months ago, and now I'm trying to build my first app :)
I am trying to display VTT subtitles from an external URL into a streaming video using AVPlayer and AVMutableComposition.
I have been trying for a few days, checking online and on Apple's documentation, but I can't manage to make it work. So far, I managed to display the subtitles, but there is no video or audio playing...
Could someone help?
Thanks in advance, I hope the code is not too confusing.
// EpisodeDetailView.swift
// OroroPlayer_v1
//
// Created by Juan Valenzuela on 2023-11-25.
//
import AVKit
import SwiftUI
struct EpisodeDetailView4: View {
@State private var episodeDetailVM = EpisodeDetailViewModel()
let episodeID: Int
@State private var player = AVPlayer()
@State private var subs = AVPlayer()
var body: some View {
VideoPlayer(player: player)
.ignoresSafeArea()
.task {
do {
try await episodeDetailVM.fetchEpisode(id: episodeID)
let episode = episodeDetailVM.episodeDetail
guard let videoURLString = episode.url else {
print("Invalid videoURL or missing data")
return
}
guard let subtitleURLString = episode.subtitles?[0].url else {
print("Invalid subtitleURLs or missing data")
return
}
let videoURL = URL(string: videoURLString)!
let subtitleURL = URL(string: subtitleURLString)!
let videoAsset = AVURLAsset(url: videoURL)
let subtitleAsset = AVURLAsset(url: subtitleURL)
let movieWithSubs = AVMutableComposition()
let videoTrack = movieWithSubs.addMutableTrack(withMediaType: .video, preferredTrackID: kCMPersistentTrackID_Invalid)
let audioTrack = movieWithSubs.addMutableTrack(withMediaType: .audio, preferredTrackID: kCMPersistentTrackID_Invalid)
let subtitleTrack = movieWithSubs.addMutableTrack(withMediaType: .text, preferredTrackID: kCMPersistentTrackID_Invalid)
//
if let videoTrackItem = try await videoAsset.loadTracks(withMediaType: .video).first {
try await videoTrack?.insertTimeRange(CMTimeRangeMake(start: .zero, duration: videoAsset.load(.duration)),
of: videoTrackItem,
at: .zero)
}
if let audioTrackItem = try await videoAsset.loadTracks(withMediaType: .audio).first {
try await audioTrack?.insertTimeRange(CMTimeRangeMake(start: .zero, duration: videoAsset.load(.duration)),
of: audioTrackItem,
at: .zero)
}
if let subtitleTrackItem = try await subtitleAsset.loadTracks(withMediaType: .text).first {
try await subtitleTrack?.insertTimeRange(CMTimeRangeMake(start: .zero, duration: videoAsset.load(.duration)),
of: subtitleTrackItem,
at: .zero)
}
let playerItem = AVPlayerItem(asset: movieWithSubs)
player = AVPlayer(playerItem: playerItem)
let playerController = AVPlayerViewController()
playerController.player = player
playerController.player?.play()
// player.play()
} catch {
print("Error: \(error.localizedDescription)")
}
}
}
}
#Preview {
EpisodeDetailView4(episodeID: 39288)
}
I am learning SwiftUI, I want to observe an AVPlayer status so I know when the videos is paused or not.
My current approach is more less like this:
I have VideosView that holds a list of a videos (in ZStack cards).
VideoViews has a VideosViewModel.
in VideosView i am calling in onAppear VideosViewModel.getItems...
struct ItemModel: Identifiable, Codable, Hashable, Equatable {
var id: String
var author: String // video owner
var url: URL? // url to the video
var player: AVPlayer? // AVPlayer created based on self.url...
mutating func setPlayer(_ avPlayer: AVPlayer) {
self.player = avPlayer
}
}
// vm
class FeedViewModel: ObservableObject {
@Published private(set) var items: [ItemModel] = []
func getItems() async {
do {
// fetch data from the API
let data = try await dataService.fetchFeeds()
// download and attach videos
downloadFeedVideos(data)
} catch {
// ....
}
}
private func downloadFeedVideos(_ feeds: [ItemModel]) {
for index in feeds.indices {
var item = feeds[index]
if let videoURL = item.url {
self.downloadQueue.queueDownloadIfFileNotExists(
videoURL,
DownloadOperation(
session: URLSession.shared,
downloadTaskURL: videoURL,
completionHandler: { [weak self] (localURL, response, error) in
guard let tempUrl = localURL else { return }
let saveResult = self?.fileManagerService.saveInTemp(tempUrl, fileName: videoURL.lastPathComponent)
switch saveResult {
case .success(let savedURL):
DispatchQueue.main.async {
// maybe this is a wrong place to have it?
item.setPlayer(AVPlayer(url: savedURL))
self?.items.append(item)
if self?.items.count ?? 0 > 1 {
// once first video is downloaded, use all device cores to fetch next videos
// all newest iOS devices has 6 cores
self?.downloadQueue.setMaxConcurrentOperationCount(.max)
}
}
case .none: break
case .failure(_):
EventTracking().track("Video download fail", [
"id": item.id,
"ulr": videoURL.absoluteString.decodeURL()
])
}
}), { fileCacheURL in
// file already downloaded
DispatchQueue.main.async {
item.setPlayer(AVPlayer(url: fileCacheURL))
self.items.append(item)
}
})
}
}
}
}
I found this article with some pseudo-code of how to track video playback state but I'm not sure how to implement it in my code....
https://developer.apple.com/documentation/avfoundation/media_playback/observing_playback_state
I have an AVPlayerViewController in my app playing video and my largest source of errors is NSURLErrorDomain Code=-1008. The underlying error they provide is Error Domain=CoreMediaErrorDomain Code=-12884 "(null)". I couldn't find what the error implies or is caused by - osstatus.com also does not have a reference to it.
I know that if you want background audio from AVPlayer you need to detatch your AVPlayer from either your AVPlayerViewController or your AVPlayerLayer in addition to having your AVAudioSession configured correctly.
I have that all squared away and background audio is fine until we introduce AVPictureInPictureController or use the PiP behavior baked into AVPlayerViewController.
If you want PiP to behave as expected when you put your app into the background by switching to another app or going to the homescreen you can't perform the detachment operation otherwise the PiP display fails.
On an iPad if PiP is active and you lock your device you continue to get background audio playback. However on an iPhone if PiP is active and you lock the device the audio pauses.
However if PiP is inactive and you lock the device the audio will pause and you have to manually tap play on the lockscreen controls. This is the same between iPad and iPhone devices.
My questions are:
Is there a way to keep background-audio playback going when PiP is inactive and the device is locked (iPhone and iPad)
Is there a way to keep background-audio playback going when PiP is active and the device is locked? (iPhone)
Hi,
for the implementation of an audio player with signed URL's, I need to be able to set an authorization header to the request for an AVURLAsset.
This works but not on Airplay when trying to stream multiple songs in a queue.
For each item I do:
let headerFields: [String: String] = ["Authorization": getIdToken()!]
super.init(url: url, options: ["AVURLAssetHTTPHeaderFieldsKey": headerFields])
But only the first 2 songs in the queue actually get this authorization header sent along, somehow it is removed for subsequent songs.
Any ideas on how I can fix this?
thanks,
Thomas