Post

Replies

Boosts

Views

Activity

Export animation from .dae
Hello guys,In WWDC 2015 - Session 606 - Enhancements to SceneKit there was an Fox example project which is available to download.Can anyone say what is the correct collada file setttings when exporting model with skeletal animation from 3D tool into .dae file? For example in the demo project there is a "walk.scn".I used 3D tool (Cheetah3D) to make a simple model with simple skeletal animation and export it in .dae, but I can't get my model to be animated on the scene.If I use non skeletal animation in 3D tool and export it in .dae then model animation on the scene works perfect.Maybe someone succeed with exporting model with skeletal animation using another 3D tool like Blender?
14
0
13k
Dec ’15
Render video in metal.
So I wanted to render video from .mov file in MTKView. Short algorithm: Read CMSampleBuffer from .mov using AVAssetReader and AVAssetReaderTrackOutput. Convert CMSampleBuffer from step 1 to MTLTexture and pass it to renderer I did those 2 steps and got the picture with twitches and I don’t know why. Link to .mov https://www.dropbox.com/s/gmzxd8j94pjhc1q/2.MOV?dl=0. Link to result https://www.dropbox.com/s/exgf1tk7oqvon25/result.mov?dl=0. The code. ViewController.swift VideoReader.swift SampleConverter.swift TextureModel.swift Renderer.swift MyMetal.metal
1
0
2.1k
Dec ’21
Using videoComposition breaks export second time (The video could not be composed).
Hello guys. I'm using Metal and custom video composition instruction and custom video compositor to change each frame of a video. It work perfect with AVPlayer. It works perfect when exporting original AVAsset for the first time but export fail if I use previously exported AVAsset. For example I've exported original.mov to exported.mov – works perfect. Then I want to use exported.mov as input (original) AVAsset – gives me error "The video could not be composed" and I don't know how to fix that. Maybe someone got same issue and can help? export function func export(arguments: Arguments) throws { let timeRange = CMTimeRange(start: .zero, duration: arguments.asset.duration) let mixComposition = AVMutableComposition() guard let sourceVideoTrack = arguments.asset.tracks(withMediaType: .video).first, let compositionVideoTrack = mixComposition.addMutableTrack(withMediaType: .video, preferredTrackID: CMPersistentTrackID()) // kCMPersistentTrackID_Invalid else { print("composition.addMutableTrack is nil") return } try compositionVideoTrack.insertTimeRange(timeRange, of: sourceVideoTrack, at: .zero) let audioMix = AVMutableAudioMix() if let sourceAudioTrack = arguments.asset.tracks(withMediaType: .audio).first, let compositionAudioTrack = mixComposition.addMutableTrack(withMediaType: .audio, preferredTrackID: CMPersistentTrackID()) // kCMPersistentTrackID_Invalid { let param = AVMutableAudioMixInputParameters(track: sourceAudioTrack) param.trackID = compositionAudioTrack.trackID try compositionAudioTrack.insertTimeRange(timeRange, of: sourceAudioTrack, at: .zero) audioMix.inputParameters = [param] } let presetName = sourceVideoTrack.hasMediaCharacteristic(.containsHDRVideo) ? AVAssetExportPresetHEVCHighestQuality : AVAssetExportPresetHighestQuality exportSession = AVAssetExportSession(asset: mixComposition, presetName: presetName) guard let exportSession = exportSession else { print("AVAssetExportSession return nil") return } guard let compositionInstruction = try CustomVideoCompositionInstruction(videoTrack: sourceVideoTrack, usedForExport: true, dependency: arguments.dependency, timeRange: timeRange) else { print("CustomVideoCompositionInstruction is nil") return } compositionInstruction.timeRange = CMTimeRange(start: .zero, duration: mixComposition.duration) compositionInstruction.videoColorStrength = arguments.colorStrength let mutableComposition = AVMutableVideoComposition() mutableComposition.renderSize = sourceVideoTrack.orientation.size(for: sourceVideoTrack.naturalSize) mutableComposition.frameDuration = CMTime(value: 1, timescale: CMTimeScale(sourceVideoTrack.nominalFrameRate)) mutableComposition.customVideoCompositorClass = CustomVideoCompositor.self mutableComposition.instructions = [compositionInstruction] exportSession.timeRange = timeRange // 1. works perfect with original AVAsset that was not exported earlier (original.mov was exported to updated.mov) // 2. gives error when using updated.mov as original AVAsset if exportSession.videoComposition is not nil exportSession.videoComposition = mutableComposition exportSession.outputFileType = .mov exportSession.outputURL = arguments.url exportSession.audioMix = audioMix timer = Timer.scheduledTimer(withTimeInterval: 0.5, repeats: true, block: { [weak self] timer in arguments.progressChanged(exportSession.progress) if exportSession.progress == 1 { timer.invalidate() self?.timer = nil } }) // 1. works perfect with original AVAsset that was not exported earlier (original.mov was exported to updated.mov) // 2. gives error when using updated.mov as original AVAsset if exportSession.videoComposition is not nil self.exportSession?.exportAsynchronously { [weak self] in guard let self = self, let session = self.exportSession else { return } if let error = session.error { print("session.error", error) // The video could not be composed when using previously exported AVAsset } self.timer?.invalidate() self.timer = nil self.exportSession = nil arguments.finished(session.status, session.error) } }
3
0
1k
Apr ’23