From 6fc47bed25895c1dc6681345046da65283aa44e9 Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Tue, 28 Nov 2023 18:42:03 +0400 Subject: [PATCH] Various fixes --- submodules/Camera/Sources/Camera.swift | 21 +- .../DrawingUI/Sources/VideoRecorder.swift | 10 +- .../QrCodeUI/Sources/QrCodeScanScreen.swift | 2 +- .../CameraScreen/Sources/CameraScreen.swift | 3 +- .../MediaEditor/Sources/MediaEditor.swift | 11 + .../Sources/MediaEditorVideoExport.swift | 320 +++--------------- .../Sources/MediaEditorScreen.swift | 2 +- 7 files changed, 81 insertions(+), 288 deletions(-) diff --git a/submodules/Camera/Sources/Camera.swift b/submodules/Camera/Sources/Camera.swift index 6e5b470df1..ad935ca89c 100644 --- a/submodules/Camera/Sources/Camera.swift +++ b/submodules/Camera/Sources/Camera.swift @@ -57,7 +57,7 @@ final class CameraDeviceContext { self.output = CameraOutput(exclusive: exclusive) } - func configure(position: Camera.Position, previewView: CameraSimplePreviewView?, audio: Bool, photo: Bool, metadata: Bool, preferWide: Bool = false) { + func configure(position: Camera.Position, previewView: CameraSimplePreviewView?, audio: Bool, photo: Bool, metadata: Bool, preferWide: Bool = false, preferLowerFramerate: Bool = false) { guard let session = self.session else { return } @@ -65,7 +65,7 @@ final class CameraDeviceContext { self.previewView = previewView self.device.configure(for: session, position: position, dual: !exclusive || additional) - self.device.configureDeviceFormat(maxDimensions: self.maxDimensions(additional: self.additional, preferWide: preferWide), maxFramerate: self.preferredMaxFrameRate) + self.device.configureDeviceFormat(maxDimensions: self.maxDimensions(additional: self.additional, preferWide: preferWide), maxFramerate: self.preferredMaxFrameRate(useLower: preferLowerFramerate)) self.input.configure(for: session, device: self.device, audio: audio) self.output.configure(for: session, device: self.device, input: self.input, previewView: previewView, audio: audio, photo: photo, metadata: metadata) @@ -90,10 +90,13 @@ final class CameraDeviceContext { } } - private var preferredMaxFrameRate: Double { + private func preferredMaxFrameRate(useLower: Bool) -> Double { if !self.exclusive { return 30.0 } + if useLower { + return 30.0 + } switch DeviceModel.current { case .iPhone15ProMax, .iPhone14ProMax, .iPhone13ProMax: return 60.0 @@ -257,7 +260,7 @@ private final class CameraContext { self._positionPromise.set(targetPosition) self.modeChange = .position - mainDeviceContext.configure(position: targetPosition, previewView: self.simplePreviewView, audio: self.initialConfiguration.audio, photo: self.initialConfiguration.photo, metadata: self.initialConfiguration.metadata, preferWide: self.initialConfiguration.preferWide) + mainDeviceContext.configure(position: targetPosition, previewView: self.simplePreviewView, audio: self.initialConfiguration.audio, photo: self.initialConfiguration.photo, metadata: self.initialConfiguration.metadata, preferWide: self.initialConfiguration.preferWide, preferLowerFramerate: self.initialConfiguration.preferLowerFramerate) self.queue.after(0.5) { self.modeChange = .none @@ -341,7 +344,7 @@ private final class CameraContext { self.additionalDeviceContext = nil self.mainDeviceContext = CameraDeviceContext(session: self.session, exclusive: true, additional: false) - self.mainDeviceContext?.configure(position: self.positionValue, previewView: self.simplePreviewView, audio: self.initialConfiguration.audio, photo: self.initialConfiguration.photo, metadata: self.initialConfiguration.metadata, preferWide: self.initialConfiguration.preferWide) + self.mainDeviceContext?.configure(position: self.positionValue, previewView: self.simplePreviewView, audio: self.initialConfiguration.audio, photo: self.initialConfiguration.photo, metadata: self.initialConfiguration.metadata, preferWide: self.initialConfiguration.preferWide, preferLowerFramerate: self.initialConfiguration.preferLowerFramerate) } self.mainDeviceContext?.output.processSampleBuffer = { [weak self] sampleBuffer, pixelBuffer, connection in guard let self, let mainDeviceContext = self.mainDeviceContext else { @@ -613,19 +616,19 @@ public final class Camera { let audio: Bool let photo: Bool let metadata: Bool - let preferredFps: Double let preferWide: Bool + let preferLowerFramerate: Bool let reportAudioLevel: Bool - public init(preset: Preset, position: Position, isDualEnabled: Bool = false, audio: Bool, photo: Bool, metadata: Bool, preferredFps: Double, preferWide: Bool = false, reportAudioLevel: Bool = false) { + public init(preset: Preset, position: Position, isDualEnabled: Bool = false, audio: Bool, photo: Bool, metadata: Bool, preferWide: Bool = false, preferLowerFramerate: Bool = false, reportAudioLevel: Bool = false) { self.preset = preset self.position = position self.isDualEnabled = isDualEnabled self.audio = audio self.photo = photo self.metadata = metadata - self.preferredFps = preferredFps self.preferWide = preferWide + self.preferLowerFramerate = preferLowerFramerate self.reportAudioLevel = reportAudioLevel } } @@ -637,7 +640,7 @@ public final class Camera { public let metrics: Camera.Metrics - public init(configuration: Camera.Configuration = Configuration(preset: .hd1920x1080, position: .back, audio: true, photo: false, metadata: false, preferredFps: 60.0), previewView: CameraSimplePreviewView? = nil, secondaryPreviewView: CameraSimplePreviewView? = nil) { + public init(configuration: Camera.Configuration = Configuration(preset: .hd1920x1080, position: .back, audio: true, photo: false, metadata: false), previewView: CameraSimplePreviewView? = nil, secondaryPreviewView: CameraSimplePreviewView? = nil) { Logger.shared.log("Camera", "Init") self.metrics = Camera.Metrics(model: DeviceModel.current) diff --git a/submodules/DrawingUI/Sources/VideoRecorder.swift b/submodules/DrawingUI/Sources/VideoRecorder.swift index 6b24d5ec38..cc117612a5 100644 --- a/submodules/DrawingUI/Sources/VideoRecorder.swift +++ b/submodules/DrawingUI/Sources/VideoRecorder.swift @@ -41,6 +41,14 @@ public final class EntityVideoRecorder { self.entity = DrawingStickerEntity(content: .dualVideoReference(true)) + var preferLowerFramerate = false + if let mainFramerate = mediaEditor.mainFramerate { + let frameRate = Int(round(mainFramerate / 30.0) * 30.0) + if frameRate == 30 { + preferLowerFramerate = true + } + } + self.camera = Camera( configuration: Camera.Configuration( preset: .hd1920x1080, @@ -49,8 +57,8 @@ public final class EntityVideoRecorder { audio: true, photo: false, metadata: false, - preferredFps: 60.0, preferWide: true, + preferLowerFramerate: preferLowerFramerate, reportAudioLevel: true ), previewView: self.previewView, diff --git a/submodules/QrCodeUI/Sources/QrCodeScanScreen.swift b/submodules/QrCodeUI/Sources/QrCodeScanScreen.swift index e5e4f2d696..7ec0009c5e 100644 --- a/submodules/QrCodeUI/Sources/QrCodeScanScreen.swift +++ b/submodules/QrCodeUI/Sources/QrCodeScanScreen.swift @@ -513,7 +513,7 @@ private final class QrCodeScanScreenNode: ViewControllerTracingNode, UIScrollVie self.errorTextNode.textAlignment = .center self.errorTextNode.isHidden = true - self.camera = Camera(configuration: .init(preset: .hd1920x1080, position: .back, audio: false, photo: true, metadata: true, preferredFps: 60), previewView: self.previewView) + self.camera = Camera(configuration: .init(preset: .hd1920x1080, position: .back, audio: false, photo: true, metadata: true), previewView: self.previewView) super.init() diff --git a/submodules/TelegramUI/Components/CameraScreen/Sources/CameraScreen.swift b/submodules/TelegramUI/Components/CameraScreen/Sources/CameraScreen.swift index 19f885ffe0..83d72e2721 100644 --- a/submodules/TelegramUI/Components/CameraScreen/Sources/CameraScreen.swift +++ b/submodules/TelegramUI/Components/CameraScreen/Sources/CameraScreen.swift @@ -1745,8 +1745,7 @@ public class CameraScreen: ViewController { isDualEnabled: self.cameraState.isDualCameraEnabled, audio: true, photo: true, - metadata: false, - preferredFps: 60.0 + metadata: false ), previewView: self.mainPreviewView, secondaryPreviewView: self.additionalPreviewView diff --git a/submodules/TelegramUI/Components/MediaEditor/Sources/MediaEditor.swift b/submodules/TelegramUI/Components/MediaEditor/Sources/MediaEditor.swift index ed0f632e78..e4b3b2db1d 100644 --- a/submodules/TelegramUI/Components/MediaEditor/Sources/MediaEditor.swift +++ b/submodules/TelegramUI/Components/MediaEditor/Sources/MediaEditor.swift @@ -1149,6 +1149,17 @@ public final class MediaEditor { self.setRate(0.0) } + public var mainFramerate: Float? { + if let player = self.player, let asset = player.currentItem?.asset, let track = asset.tracks(withMediaType: .video).first { + if track.nominalFrameRate > 0.0 { + return track.nominalFrameRate + } else if track.minFrameDuration.seconds > 0.0 { + return Float(1.0 / track.minFrameDuration.seconds) + } + } + return nil + } + private func setRate(_ rate: Float) { let hostTime: UInt64 = mach_absolute_time() let time: TimeInterval = 0 diff --git a/submodules/TelegramUI/Components/MediaEditor/Sources/MediaEditorVideoExport.swift b/submodules/TelegramUI/Components/MediaEditor/Sources/MediaEditorVideoExport.swift index 6a88731dfd..232a481538 100644 --- a/submodules/TelegramUI/Components/MediaEditor/Sources/MediaEditorVideoExport.swift +++ b/submodules/TelegramUI/Components/MediaEditor/Sources/MediaEditorVideoExport.swift @@ -332,9 +332,15 @@ public final class MediaEditorVideoExport { private var reader: AVAssetReader? private var videoOutput: AVAssetReaderOutput? private var textureRotation: TextureRotation = .rotate0Degrees + private var frameRate: Float? + private var additionalVideoOutput: AVAssetReaderOutput? private var additionalTextureRotation: TextureRotation = .rotate0Degrees + private var additionalFrameRate: Float? private var additionalVideoDuration: Double? + + private var mainComposeFramerate: Float? + private var audioOutput: AVAssetReaderOutput? private var writer: MediaEditorVideoExportWriter? @@ -368,7 +374,6 @@ public final class MediaEditorVideoExport { if FileManager.default.fileExists(atPath: outputPath) { try? FileManager.default.removeItem(atPath: outputPath) } - self.setup() let _ = NotificationCenter.default.addObserver(forName: UIApplication.willEnterForegroundNotification, object: nil, queue: nil, using: { [weak self] _ in @@ -644,19 +649,23 @@ public final class MediaEditorVideoExport { } } - var sourceFrameRate: Float = 0.0 - let effectiveVideoTrack = mainVideoTrack ?? additionalVideoTrack - if let effectiveVideoTrack { - if effectiveVideoTrack.nominalFrameRate > 0.0 { - sourceFrameRate = effectiveVideoTrack.nominalFrameRate - } else if effectiveVideoTrack.minFrameDuration.seconds > 0.0 { - sourceFrameRate = Float(1.0 / effectiveVideoTrack.minFrameDuration.seconds) - } else { - sourceFrameRate = 30.0 + func frameRate(for track: AVCompositionTrack) -> Float { + if track.nominalFrameRate > 0.0 { + return track.nominalFrameRate + } else if track.minFrameDuration.seconds > 0.0 { + return Float(1.0 / track.minFrameDuration.seconds) } - } else { - sourceFrameRate = 30.0 + return 30.0 } + + if let mainVideoTrack { + self.frameRate = frameRate(for: mainVideoTrack) + } + if let additionalVideoTrack { + self.additionalFrameRate = frameRate(for: additionalVideoTrack) + } + let sourceFrameRate: Float = (self.frameRate ?? self.additionalFrameRate) ?? 30.0 + self.mainComposeFramerate = round(sourceFrameRate / 30.0) * 30.0 writer.setupVideoInput(configuration: self.configuration, preferredTransform: nil, sourceFrameRate: sourceFrameRate) if let reader { @@ -678,252 +687,7 @@ public final class MediaEditorVideoExport { } } -// private func setupWithAsset(_ asset: AVAsset, additionalAsset: AVAsset?, isStory: Bool) { -// var inputAsset = asset -// -// var inputAudioMix: AVMutableAudioMix? -// if let audioData = self.configuration.values.audioTrack { -// let mixComposition = AVMutableComposition() -// let audioPath = fullDraftPath(peerId: self.configuration.values.peerId, path: audioData.path) -// let audioAsset = AVURLAsset(url: URL(fileURLWithPath: audioPath)) -// -// guard -// let videoTrack = mixComposition.addMutableTrack(withMediaType: .video, preferredTrackID: kCMPersistentTrackID_Invalid), -// let musicTrack = mixComposition.addMutableTrack(withMediaType: .audio, preferredTrackID: kCMPersistentTrackID_Invalid), -// let videoAssetTrack = asset.tracks(withMediaType: .video).first, -// let musicAssetTrack = audioAsset.tracks(withMediaType: .audio).first, -// let duration = self.durationValue -// else { -// print("error") -// return -// } -// videoTrack.preferredTransform = videoAssetTrack.preferredTransform -// -// let timeRange: CMTimeRange = CMTimeRangeMake(start: .zero, duration: duration) -// try? videoTrack.insertTimeRange(timeRange, of: videoAssetTrack, at: .zero) -// -// if let audioAssetTrack = asset.tracks(withMediaType: .audio).first, let audioTrack = mixComposition.addMutableTrack(withMediaType: .audio, preferredTrackID: kCMPersistentTrackID_Invalid), !self.configuration.values.videoIsMuted { -// try? audioTrack.insertTimeRange(timeRange, of: audioAssetTrack, at: .zero) -// } -// -// var musicRange = timeRange -// let musicStartTime = self.configuration.audioStartTime -// if let audioTrackRange = self.configuration.audioTimeRange { -// musicRange = audioTrackRange -// } -// if musicStartTime + musicRange.duration > duration { -// musicRange = CMTimeRange(start: musicRange.start, end: duration - musicStartTime) -// } -// try? musicTrack.insertTimeRange(musicRange, of: musicAssetTrack, at: musicStartTime) -// -// if let volume = self.configuration.values.audioTrackVolume, volume < 1.0 { -// let audioMix = AVMutableAudioMix() -// var audioMixParam: [AVMutableAudioMixInputParameters] = [] -// let param: AVMutableAudioMixInputParameters = AVMutableAudioMixInputParameters(track: musicTrack) -// param.trackID = musicTrack.trackID -// param.setVolume(Float(volume), at: CMTime.zero) -// audioMixParam.append(param) -// audioMix.inputParameters = audioMixParam -// inputAudioMix = audioMix -// } -// -// inputAsset = mixComposition -// } -// -// self.reader = try? AVAssetReader(asset: inputAsset) -// -// var mirror = false -// if additionalAsset == nil, self.configuration.values.videoIsMirrored { -// mirror = true -// } -// -// self.textureRotation = textureRotatonForAVAsset(asset, mirror: mirror) -// -// if let additionalAsset { -// self.additionalReader = try? AVAssetReader(asset: additionalAsset) -// self.additionalTextureRotation = textureRotatonForAVAsset(additionalAsset, mirror: true) -// } -// guard let reader = self.reader else { -// return -// } -// if let timeRange = self.configuration.timeRange { -// reader.timeRange = timeRange -// if let additionalTimeRange = self.configuration.additionalVideoTimeRange { -// self.additionalReader?.timeRange = additionalTimeRange -// } else { -// self.additionalReader?.timeRange = timeRange -// } -// } else if asset.duration.seconds > 60.0 && isStory { -// let trimmedRange = CMTimeRange(start: CMTime(seconds: 0.0, preferredTimescale: CMTimeScale(NSEC_PER_SEC)), end: CMTime(seconds: 60.0, preferredTimescale: CMTimeScale(NSEC_PER_SEC))) -// reader.timeRange = trimmedRange -// if let additionalTimeRange = self.configuration.additionalVideoTimeRange { -// self.additionalReader?.timeRange = additionalTimeRange -// } else { -// self.additionalReader?.timeRange = trimmedRange -// } -// } -// -// self.writer = MediaEditorVideoAVAssetWriter() -// guard let writer = self.writer else { -// return -// } -// writer.setup(configuration: self.configuration, outputPath: self.outputPath) -// -// let videoTracks = inputAsset.tracks(withMediaType: .video) -// let additionalVideoTracks = additionalAsset?.tracks(withMediaType: .video) -// if videoTracks.count > 0 { -// var sourceFrameRate: Float = 0.0 -// let colorProperties: [String: Any] = [ -// AVVideoColorPrimariesKey: AVVideoColorPrimaries_ITU_R_709_2, -// AVVideoTransferFunctionKey: AVVideoTransferFunction_ITU_R_709_2, -// AVVideoYCbCrMatrixKey: AVVideoYCbCrMatrix_ITU_R_709_2 -// ] -// -// let outputSettings: [String: Any] = [ -// kCVPixelBufferPixelFormatTypeKey as String: kCVPixelFormatType_420YpCbCr8BiPlanarFullRange, -// kCVPixelBufferMetalCompatibilityKey as String: true, -// AVVideoColorPropertiesKey: colorProperties -// ] -// -// let originalDimensions = self.configuration.values.originalDimensions -// var isNotFullscreen = false -// var hasNonIdentityTransform = false -// if case .video(_, true) = self.subject { -// if originalDimensions.width > 0 && abs((Double(originalDimensions.height) / Double(originalDimensions.width)) - 1.7777778) > 0.001 { -// isNotFullscreen = true -// } -// if let videoTrack = videoTracks.first { -// hasNonIdentityTransform = !videoTrack.preferredTransform.isIdentity -// } -// } -// var preferredTransform: CGAffineTransform? -// if let videoTrack = videoTracks.first, !self.configuration.values.requiresComposing && !isNotFullscreen && !hasNonIdentityTransform { -// preferredTransform = videoTrack.preferredTransform -// } else { -// self.setupComposer() -// } -// let videoOutput = AVAssetReaderTrackOutput(track: videoTracks.first!, outputSettings: outputSettings) -// videoOutput.alwaysCopiesSampleData = true -// if reader.canAdd(videoOutput) { -// reader.add(videoOutput) -// } else { -// self.internalStatus = .finished -// self.statusValue = .failed(.addVideoOutput) -// } -// self.videoOutput = videoOutput -// -// if let additionalReader = self.additionalReader, let additionalVideoTrack = additionalVideoTracks?.first { -// let additionalVideoOutput = AVAssetReaderTrackOutput(track: additionalVideoTrack, outputSettings: outputSettings) -// additionalVideoOutput.alwaysCopiesSampleData = true -// if additionalReader.canAdd(additionalVideoOutput) { -// additionalReader.add(additionalVideoOutput) -// } -// self.additionalVideoOutput = additionalVideoOutput -// } -// -// if let videoTrack = videoTracks.first { -// if videoTrack.nominalFrameRate > 0.0 { -// sourceFrameRate = videoTrack.nominalFrameRate -// } else if videoTrack.minFrameDuration.seconds > 0.0 { -// sourceFrameRate = Float(1.0 / videoTrack.minFrameDuration.seconds) -// } else { -// sourceFrameRate = 30.0 -// } -// } else { -// sourceFrameRate = 30.0 -// } -// writer.setupVideoInput(configuration: self.configuration, preferredTransform: preferredTransform, sourceFrameRate: sourceFrameRate) -// } else { -// self.videoOutput = nil -// } -// -// let audioTracks = inputAsset.tracks(withMediaType: .audio) -// if audioTracks.count > 0, !self.configuration.values.videoIsMuted || self.configuration.values.audioTrack != nil { -// let audioOutput = AVAssetReaderAudioMixOutput(audioTracks: audioTracks, audioSettings: nil) -// audioOutput.audioMix = inputAudioMix -// audioOutput.alwaysCopiesSampleData = false -// if reader.canAdd(audioOutput) { -// reader.add(audioOutput) -// } else { -// self.internalStatus = .finished -// self.statusValue = .failed(.addAudioOutput) -// } -// self.audioOutput = audioOutput -// -// writer.setupAudioInput(configuration: self.configuration) -// } else { -// self.audioOutput = nil -// } -// -// if videoTracks.count == 0 && audioTracks.count == 0 { -// self.internalStatus = .finished -// self.statusValue = .failed(.noTracksFound) -// } -// } -// -// private func setupWithImage(_ image: UIImage) { -// Logger.shared.log("VideoExport", "Setup with image") -// -// self.setupComposer() -// -// var inputAudioMix: AVMutableAudioMix? -// -// self.writer = MediaEditorVideoAVAssetWriter() -// guard let writer = self.writer else { -// return -// } -// writer.setup(configuration: self.configuration, outputPath: self.outputPath) -// writer.setupVideoInput(configuration: self.configuration, preferredTransform: nil, sourceFrameRate: 30.0) -// -// if let audioData = self.configuration.values.audioTrack { -// let mixComposition = AVMutableComposition() -// let audioPath = fullDraftPath(peerId: self.configuration.values.peerId, path: audioData.path) -// let audioAsset = AVURLAsset(url: URL(fileURLWithPath: audioPath)) -// -// if let musicAssetTrack = audioAsset.tracks(withMediaType: .audio).first, -// let musicTrack = mixComposition.addMutableTrack(withMediaType: .audio, preferredTrackID: kCMPersistentTrackID_Invalid) { -// do { -// let reader = try AVAssetReader(asset: mixComposition) -// -// var musicRange = CMTimeRange(start: .zero, duration: CMTime(seconds: min(15.0, audioData.duration), preferredTimescale: CMTimeScale(NSEC_PER_SEC))) -// if let audioTrackRange = self.configuration.audioTimeRange { -// musicRange = audioTrackRange -// } -// try? musicTrack.insertTimeRange(musicRange, of: musicAssetTrack, at: .zero) -// -// if let volume = self.configuration.values.audioTrackVolume, volume < 1.0 { -// let audioMix = AVMutableAudioMix() -// var audioMixParam: [AVMutableAudioMixInputParameters] = [] -// let param: AVMutableAudioMixInputParameters = AVMutableAudioMixInputParameters(track: musicTrack) -// param.trackID = musicTrack.trackID -// param.setVolume(Float(volume), at: CMTime.zero) -// audioMixParam.append(param) -// audioMix.inputParameters = audioMixParam -// inputAudioMix = audioMix -// } -// -// let audioTracks = mixComposition.tracks(withMediaType: .audio) -// let audioOutput = AVAssetReaderAudioMixOutput(audioTracks: audioTracks, audioSettings: nil) -// audioOutput.audioMix = inputAudioMix -// audioOutput.alwaysCopiesSampleData = false -// if reader.canAdd(audioOutput) { -// reader.add(audioOutput) -// -// self.reader = reader -// self.audioOutput = audioOutput -// -// writer.setupAudioInput(configuration: self.configuration) -// } else { -// self.internalStatus = .finished -// self.statusValue = .failed(.addAudioOutput) -// } -// } catch { -// self.internalStatus = .finished -// self.statusValue = .failed(.addAudioOutput) -// } -// } -// } -// } + private var skippingAdditionalCopyUpdate = false private func encodeVideo() -> Bool { guard let writer = self.writer else { @@ -977,20 +741,30 @@ public final class MediaEditorVideoExport { if let additionalVideoOutput = self.additionalVideoOutput { if let mainTimestamp, mainTimestamp < self.configuration.additionalVideoStartTime { - } else if let sampleBuffer = additionalVideoOutput.copyNextSampleBuffer() { - if let pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer) { - let timestamp = CMSampleBufferGetPresentationTimeStamp(sampleBuffer) - additionalInput = .videoBuffer(VideoPixelBuffer( - pixelBuffer: pixelBuffer, - rotation: self.additionalTextureRotation, - timestamp: timestamp - )) - - if !updatedProgress, let duration = self.durationValue { - let startTime = self.reader?.timeRange.start.seconds ?? 0.0 - let progress = (timestamp.seconds - startTime) / duration.seconds - self.statusValue = .progress(Float(progress)) - updatedProgress = true + } else { + if self.skippingAdditionalCopyUpdate { + self.skippingAdditionalCopyUpdate = false + } else if let sampleBuffer = additionalVideoOutput.copyNextSampleBuffer() { + if let pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer) { + let timestamp = CMSampleBufferGetPresentationTimeStamp(sampleBuffer) + additionalInput = .videoBuffer(VideoPixelBuffer( + pixelBuffer: pixelBuffer, + rotation: self.additionalTextureRotation, + timestamp: timestamp + )) + + if !updatedProgress, let duration = self.durationValue { + let startTime = self.reader?.timeRange.start.seconds ?? 0.0 + let progress = (timestamp.seconds - startTime) / duration.seconds + self.statusValue = .progress(Float(progress)) + updatedProgress = true + } + } + if let additionalFrameRate = self.additionalFrameRate, let mainComposeFramerate = self.mainComposeFramerate { + let additionalFrameRate = round(additionalFrameRate / 30.0) * 30.0 + if Int(mainComposeFramerate) == Int(additionalFrameRate) * 2 { + self.skippingAdditionalCopyUpdate = true + } } } } @@ -1026,8 +800,6 @@ public final class MediaEditorVideoExport { pool: writer.pixelBufferPool, completion: { pixelBuffer in if let pixelBuffer { - print("writing: \(timestamp)") - if !writer.appendPixelBuffer(pixelBuffer, at: timestamp) { writer.markVideoAsFinished() appendFailed = true diff --git a/submodules/TelegramUI/Components/MediaEditorScreen/Sources/MediaEditorScreen.swift b/submodules/TelegramUI/Components/MediaEditorScreen/Sources/MediaEditorScreen.swift index 6ac152c06c..762e1f8f6b 100644 --- a/submodules/TelegramUI/Components/MediaEditorScreen/Sources/MediaEditorScreen.swift +++ b/submodules/TelegramUI/Components/MediaEditorScreen/Sources/MediaEditorScreen.swift @@ -4161,7 +4161,7 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate self.adminedChannels.set(.single([]) |> then(self.context.engine.peers.channelsForStories())) self.closeFriends.set(self.context.engine.data.get(TelegramEngine.EngineData.Item.Contacts.CloseFriends())) - if let _ = self.forwardSource { + if self.forwardSource != nil || self.isEditingStory { self.audioSessionDisposable = self.context.sharedContext.mediaManager.audioSession.push(audioSessionType: .recordWithOthers, activate: { _ in if #available(iOS 13.0, *) { try? AVAudioSession.sharedInstance().setAllowHapticsAndSystemSoundsDuringRecording(true)