Platforms to show: All Mac Windows Linux Cross-Platform
/AVFoundation/Overlay video track with picture
Required plugins for this example: MBS AVFoundation Plugin, MBS Util Plugin, MBS MacCG Plugin, MBS MacCF Plugin, MBS Main Plugin, MBS MacBase Plugin
You find this example project in your Plugins Download as a Xojo project file within the examples folder: /AVFoundation/Overlay video track with picture
This example is the version from Tue, 24th Sep 2018.
Project "Overlay video track with picture.xojo_binary_project"
Class App Inherits Application
Const kEditClear = "&Delete"
Const kFileQuit = "&Quit"
Const kFileQuitShortcut = ""
EventHandler Sub Open()
AVEvents = new MyAVFoundationMBS
End EventHandler
Property AVEvents As MyAVFoundationMBS
End Class
MenuBar MainMenuBar
MenuItem FileMenu = "&File"
MenuItem FileQuit = "#App.kFileQuit"
MenuItem EditMenu = "&Edit"
MenuItem EditUndo = "&Undo"
MenuItem EditSeparator1 = "-"
MenuItem EditCut = "Cu&t"
MenuItem EditCopy = "&Copy"
MenuItem EditPaste = "&Paste"
MenuItem EditClear = "#App.kEditClear"
MenuItem EditSeparator2 = "-"
MenuItem EditSelectAll = "Select &All"
End MenuBar
Class MainWindow Inherits Window
Control SelectVideoFileButton Inherits PushButton
ControlInstance SelectVideoFileButton Inherits PushButton
EventHandler Sub Action()
dim f as FolderItem = GetOpenFolderItem(MovieFileTypes.All)
if f<>Nil then
dim a as AVURLAssetMBS = AVURLAssetMBS.URLAssetWithFile(F)
if a<>Nil then
VideoFilePath.Text = f.DisplayName
InputVideoFile = f
InputVideoAsset = a
end if
end if
SaveMovieButton.Enabled = InputImage <> nil and InputVideoAsset <> nil
End EventHandler
End Control
Control SelectPictureFileButton Inherits PushButton
ControlInstance SelectPictureFileButton Inherits PushButton
EventHandler Sub Action()
dim f as FolderItem = GetOpenFolderItem(ImageFileTypes.All)
if f<>Nil then
dim img as CGImageMBS = CGImageMBS.CreateImageWithFile(F)
if img<>Nil then
PictureFilePath.Text = f.DisplayName
InputImageFile = f
InputImage = img
end if
end if
SaveMovieButton.Enabled = InputImage <> nil and InputVideoAsset <> nil
End EventHandler
End Control
Control VideoFilePath Inherits Label
ControlInstance VideoFilePath Inherits Label
End Control
Control PictureFilePath Inherits Label
ControlInstance PictureFilePath Inherits Label
End Control
Control SaveMovieButton Inherits PushButton
ControlInstance SaveMovieButton Inherits PushButton
EventHandler Sub Action()
dim n as string = InputVideoFile.NameWithoutExtensionMBS
n = n + " copy"
dim f as FolderItem = GetSaveFolderItem(MovieFileTypes.VideoXM4v, n)
if f<>Nil then
OutputVideoFile = f
run
end if
End EventHandler
End Control
Control Label1 Inherits Label
ControlInstance Label1 Inherits Label
End Control
EventHandler Sub Open()
#if DebugBuild then
dim f as FolderItem = SpecialFolder.Desktop.Child("test.jpg")
if f<>Nil then
dim img as CGImageMBS = CGImageMBS.CreateImageWithFile(F)
if img<>Nil then
PictureFilePath.Text = f.DisplayName
InputImageFile = f
InputImage = img
end if
end if
f = SpecialFolder.Desktop.Child("test.m4v")
if f<>Nil then
dim a as AVURLAssetMBS = AVURLAssetMBS.URLAssetWithFile(F)
if a<>Nil then
VideoFilePath.Text = f.DisplayName
InputVideoFile = f
InputVideoAsset = a
end if
end if
SaveMovieButton.Enabled = InputImage <> nil and InputVideoAsset <> nil
#endif
End EventHandler
Sub run()
const kCMPersistentTrackID_Invalid = 0
// load video and find tracks
dim videoAsset as AVAssetMBS = InputVideoAsset
dim mixComposition as AVMutableCompositionMBS = AVMutableCompositionMBS.composition
dim type as string = AVFoundationMBS.AVMediaTypeVideo
dim compositionVideoTrack as AVMutableCompositionTrackMBS = mixComposition.addMutableTrackWithMediaType(type, kCMPersistentTrackID_Invalid)
dim clipVideoTracks() as AVAssetTrackMBS = videoAsset.tracksWithMediaType(type)
dim clipVideoTrack as AVAssetTrackMBS = clipVideoTracks(0)
dim error as NSErrorMBS
dim timeRange as CMTimeRangeMBS = CMTimeRangeMBS.Make(CMTimeMBS.kCMTimeZero, videoAsset.duration)
if not compositionVideoTrack.insertTimeRange(timeRange, clipVideoTrack, CMTimeMBS.kCMTimeZero, error) then
Break
end if
compositionVideoTrack.preferredTransform = clipVideoTrack.preferredTransform
// build layer with image
dim myImage as CGImageMBS = InputImage
dim layer as CALayerMBS = CALayerMBS.layer
dim videoSize as CGSizeMBS = videoAsset.naturalSize
layer.contents = myImage
// center
dim x as Double = (videoSize.Width - myImage.Width ) / 2
dim y as Double = (videoSize.Height - myImage.Height) / 2
layer.frame = CGMakeRectMBS(x, y, myImage.Width, myImage.Height)
layer.opacity = 0.65
dim parentLayer as CALayerMBS = CALayerMBS.layer
dim videoLayer as CALayerMBS = CALayerMBS.layer
parentLayer.frame = CGMakeRectMBS(0, 0, videoSize.width, videoSize.height)
videoLayer.frame = CGMakeRectMBS(0, 0, videoSize.width, videoSize.height)
parentLayer.addSublayer videoLayer
parentLayer.addSublayer Layer
// Now we are creating the composition and add the instructions to insert the layer:
dim videoComp as AVMutableVideoCompositionMBS = AVMutableVideoCompositionMBS.mutableVideoComposition
videoComp.renderSize = videoSize
videoComp.frameDuration = CMTimeMBS.Make(1, 30)
videoComp.animationTool = AVVideoCompositionCoreAnimationToolMBS.videoCompositionCoreAnimationToolWithPostProcessingAsVideoLayer(videoLayer, parentLayer)
/// instruction
dim instruction as AVMutableVideoCompositionInstructionMBS = AVMutableVideoCompositionInstructionMBS.videoCompositionInstruction
instruction.timeRange = CMTimeRangeMBS.Make(CMTimeMBS.kCMTimeZero, mixComposition.duration)
dim videoTracks() as AVAssetTrackMBS = mixComposition.tracksWithMediaType(type)
dim videoTrack as AVAssetTrackMBS = videoTracks(0)
dim layerInstruction as AVMutableVideoCompositionLayerInstructionMBS = AVMutableVideoCompositionLayerInstructionMBS.videoCompositionLayerInstructionWithAssetTrack(videoTrack)
instruction.setLayerInstructions array(layerInstruction)
videoComp.setInstructions array(instruction)
// add audio back
dim clipAudioTracks() as AVAssetTrackMBS = videoAsset.tracksWithMediaType(AVFoundationMBS.AVMediaTypeAudio)
dim clipAudioTrack as AVAssetTrackMBS = clipAudioTracks(0)
dim compositionAudioTrack as AVMutableCompositionTrackMBS = mixComposition.addMutableTrackWithMediaType(AVFoundationMBS.AVMediaTypeAudio, kCMPersistentTrackID_Invalid)
if not compositionAudioTrack.insertTimeRange(timeRange, clipAudioTrack, CMTimeMBS.kCMTimeZero, error) then
Break
end if
// export
dim pw as new ProgressWindow
pw.info.Text = "Writing "+OutputVideoFile.name
assetExport = new AVAssetExportSessionMBS(mixComposition, AVAssetExportSessionMBS.AVAssetExportPresetAppleM4VWiFi)
assetExport.videoComposition = videoComp
if InputVideoFile.Exists then
InputVideoFile.Delete
end if
assetExport.outputFileType = AVFoundationMBS.AVFileTypeAppleM4V
assetExport.outputFile = OutputVideoFile
assetExport.shouldOptimizeForNetworkUse = true
pw.assetExport = assetExport
pw.show
assetExport.exportAsynchronously pw
End Sub
Property InputImage As CGImageMBS
Property InputImageFile As FolderItem
Property InputVideoAsset As AVURLAssetMBS
Property InputVideoFile As FolderItem
Property OutputVideoFile As FolderItem
Property assetExport As AVAssetExportSessionMBS
End Class
Class MyAVFoundationMBS Inherits AVFoundationMBS
EventHandler Sub exportAsynchronouslyCompleted(ExportSession as AVAssetExportSessionMBS, tag as variant)
dim pw as ProgressWindow = tag
pw.close
dim f as FolderItem = ExportSession.outputFile
if f<>Nil then
f.Launch(True)
end if
End EventHandler
End Class
ImageFileTypes
Filetype image/jpeg
Filetype image/png
Filetype image/tiff
End ImageFileTypes
MovieFileTypes
Filetype video/quicktime
Filetype video/mpeg
Filetype video/mp4
Filetype video/x-m4v
Filetype video/avi
End MovieFileTypes
Class ProgressWindow Inherits Window
Control Info Inherits Label
ControlInstance Info Inherits Label
End Control
Control ProgressBar1 Inherits ProgressBar
ControlInstance ProgressBar1 Inherits ProgressBar
End Control
Control Timer1 Inherits Timer
ControlInstance Timer1 Inherits Timer
EventHandler Sub Action()
dim p as integer = 100 * assetExport.progress
if ProgressBar1.Value <> p then
ProgressBar1.Maximum = 100
ProgressBar1.Value = p
end if
End EventHandler
End Control
Property assetExport As AVAssetExportSessionMBS
End Class
End Project
The items on this page are in the following plugins: MBS AVFoundation Plugin.