diff --git a/kplayer/server/kplayer.js b/kplayer/server/kplayer.js index c63605d..b7e90eb 100644 --- a/kplayer/server/kplayer.js +++ b/kplayer/server/kplayer.js @@ -341,6 +341,11 @@ app.get('/webdl', function (req, res) { return } + if (q.filter((i) => i.folder === n).length > 0) { + res.send("exists") + return + } + q.push({url: p, folder: n, cookie: c}); console.log("all urls pushed"); diff --git a/kplayer/video/SVideoModel.swift b/kplayer/video/SVideoModel.swift index 46115de..e940a84 100644 --- a/kplayer/video/SVideoModel.swift +++ b/kplayer/video/SVideoModel.swift @@ -30,6 +30,8 @@ class SVideoModel : ObservableObject { @Published var speed: Float = 1.0 @Published var height: Int = 0 @Published var nominalFrameRate: Int = 0 + @Published var bitRate: Int = 0 + @Published var codec: String = "avc1" @Published var currentURL: URL? diff --git a/kplayer/video/SVideoPlayer.swift b/kplayer/video/SVideoPlayer.swift index e058b16..e24973e 100644 --- a/kplayer/video/SVideoPlayer.swift +++ b/kplayer/video/SVideoPlayer.swift @@ -42,6 +42,9 @@ struct SVideoPlayer: View, EditItemDelegate { .makeConnectable() .autoconnect() + let bitrateChanged = NotificationCenter.default + .publisher(for: NSNotification.Name.AVPlayerItemNewAccessLogEntry) + let steps: [Float] = [0.25, 0.5, 1.0, 2.0] init(completionHandler: ((Bool) -> ())?, model: SVideoModel) { @@ -117,7 +120,7 @@ struct SVideoPlayer: View, EditItemDelegate { Text(model.currentSnapshot.name).foregroundColor(Color.blue) - Text(" (\(model.height),\(model.nominalFrameRate)").foregroundColor(Color.blue) + Text("(\(model.codec) \(model.height), \(model.nominalFrameRate), \(model.bitRate)m)").foregroundColor(Color.blue) ScrollView(.horizontal, showsIndicators: false) { HStack { @@ -127,6 +130,7 @@ struct SVideoPlayer: View, EditItemDelegate { }) { AsyncImage(item: item, placeholder: { Text("Loading ...") }, image: { Image(uiImage: $0).resizable() }) + .overlay(Image(systemName: "repeat.circle").offset(x: 20, y: -20).opacity((item.length > 0.0) ? 1 : 0)) } } } @@ -384,6 +388,14 @@ struct SVideoPlayer: View, EditItemDelegate { .onReceive(orientationChanged) { _ in self.orientation = UIDevice.current.orientation } + .onReceive(bitrateChanged) { notification in + guard let playerItem = notification.object as? AVPlayerItem, + let lastEvent = playerItem.accessLog()?.events.last else { + return + } + + model.bitRate = Int(lastEvent.indicatedBitrate / 1024 / 1024) + } } @@ -571,7 +583,19 @@ struct SVideoPlayer: View, EditItemDelegate { let heightSpace = model.proxy!.size.height * 2 var height = heightSpace if let i = player.currentItem { - model.nominalFrameRate = await i.asset.load(.nominalFrameRate) + Task.init { + for t in i.asset.tracks { + if t.mediaType == .video { + model.nominalFrameRate = try await Int(t.load(.nominalFrameRate)) + + if let formats = t.formatDescriptions as? [CMFormatDescription] { + for format in formats { + printFourCC(CMFormatDescriptionGetMediaSubType(format)) + } + } + } + } + } height = i.presentationSize.height } model.height = Int(height) @@ -595,6 +619,19 @@ struct SVideoPlayer: View, EditItemDelegate { } + func printFourCC(_ fcc: FourCharCode) { + let bytes: [CChar] = [ + CChar((fcc >> 24) & 0xff), + CChar((fcc >> 16) & 0xff), + CChar((fcc >> 8) & 0xff), + CChar(fcc & 0xff), + 0] + + let result = String(cString: bytes) + let characterSet = CharacterSet.whitespaces + model.codec = result.trimmingCharacters(in: characterSet) + } + func captureZoom() { model.currentSnapshot.scale = model.scale model.currentSnapshot.offset = CGPoint(x: model.dragOffset.width, y: model.dragOffset.height)