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?
Post
Replies
Boosts
Views
Activity
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
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)
}
}