MAWT - Movie Automation With TclTop
MAWT
offers parts of the video functionality of FFmpeg at the Tcl scripting level. This is accomplished by wrapping parts of the FFmpeg library with the help of SWIG.
Important links:
::mawtTop
Commandsmawt, Top
GetErrorMessage [::mawt]mawt, Top
Get the last error message issued by MAWT.
See also
GetFfmpegVersion, GetVersion, SetDebugMode
proc ::mawt::GetErrorMessage {} { # Get the last error message issued by MAWT. # # See also: GetFfmpegVersion GetVersion SetDebugMode return [mawt::MawtGetErrorMessage] }
GetFfmpegVersion [::mawt]mawt, Top
Get FFMPEG library version string.
Return value
Returns the version of the wrapped FFMPEG library as a string. The version is returned as Major.Minor.Patch
.
See also
GetVersion, SetDebugMode, GetErrorMessage
proc ::mawt::GetFfmpegVersion {} { # Get FFMPEG library version string. # # Returns the version of the wrapped FFMPEG library as a string. # The version is returned as `Major.Minor.Patch`. # # See also: GetVersion SetDebugMode GetErrorMessage return [mawt::MawtGetFfmpegVersion] }
GetVersion [::mawt]mawt, Top
Get MAWT library version string.
Return value
Returns the version of the MAWT library as a string. The version is returned as Major.Minor.Patch
.
See also
GetFfmpegVersion, SetDebugMode, GetErrorMessage
proc ::mawt::GetVersion {} { # Get MAWT library version string. # # Returns the version of the MAWT library as a string. # The version is returned as `Major.Minor.Patch`. # # See also: GetFfmpegVersion SetDebugMode GetErrorMessage return [mawt::MawtGetVersion] }
SetDebugMode [::mawt]mawt, Top
Enable or disable the debug mode of the MAWT library.
Parameters
onOff | Boolean value to enable or disable the debug mode. |
See also
GetFfmpegVersion, GetVersion, GetErrorMessage
proc ::mawt::SetDebugMode {onOff} { # Enable or disable the debug mode of the MAWT library. # # onOff - Boolean value to enable or disable the debug mode. # # See also: GetFfmpegVersion GetVersion GetErrorMessage mawt::MawtSetDebugMode [expr {bool($onOff)}] }
VideoExport [::mawt]mawt, Top
Export video frames into a series of image files.
Parameters
movieFile | Movie file name. |
imgFilePattern | Pattern for image output files. Must contain a printf like integer format specifier. |
args | Options described below. |
-end <int> | End frame. Default: Last video frame. |
-format <string> | Format string for "photo write" command. Default: PNG. Example: -format "JPEG -quality 75". |
-start <int> | Start frame. Default: First video frame. |
-verbose <bool> | Print verbose messages. Default: false. |
See also
proc ::mawt::VideoExport {movieFile imgFilePattern args} { # Export video frames into a series of image files. # # movieFile - Movie file name. # imgFilePattern - Pattern for image output files. # Must contain a printf like integer format specifier. # args - Options described below. # # -start <int> - Start frame. Default: First video frame. # -end <int> - End frame. Default: Last video frame. # -format <string> - Format string for "photo write" command. Default: PNG. # Example: -format "JPEG -quality 75". # -verbose <bool> - Print verbose messages. Default: false. # # See also: VideoImport set startFrame -1 set endFrame -1 set verbose 0 set format "PNG" foreach { key value } $args { switch -exact $key { "-start" { set startFrame [expr {int($value)}] } "-end" { set endFrame [expr {int($value)}] } "-format" { set format $value } "-verbose" { set verbose [expr {bool($value)}] } } } set videoObj [mawt Video new $movieFile "r"] set numBytes [$videoObj Start] set tx [$videoObj GetWidth] set ty [$videoObj GetHeight] set vectorObj [mawt Vector new $numBytes] image create photo VideoFrame -width $tx -height $ty set numFrames [$videoObj GetNumFrames] if { $startFrame < 0 } { set startFrame 0 } if { $endFrame < 0 || $endFrame > $numFrames } { set endFrame [expr {$numFrames - 1}] } if { $verbose } { puts "Input file : $movieFile" puts "Output files: $imgFilePattern" puts "Start : $startFrame" puts "End : $endFrame" puts "Image format: $format" } set numExportedImgs 0 for { set i $startFrame } { $i <= $endFrame } { incr i } { $videoObj Lock $videoObj GetNextImage [$vectorObj Get] 0 $videoObj Unlock $vectorObj ToPhoto VideoFrame $tx $ty set outFileName [format $imgFilePattern $i] set retVal [catch { VideoFrame write $outFileName -format $format } errMsg] if { $retVal != 0 } { puts "Error saving image:\n$errMsg" return false } incr numExportedImgs } $vectorObj destroy $videoObj destroy return $numExportedImgs }
VideoImport [::mawt]mawt, Top
Generate a video by importing a series of image files.
Parameters
imgFilePattern | Pattern for image input files or a list of image input files. If file pattern, the file names must contain a printf like integer format specifier. |
movieFile | Movie output file name. |
args | Options described below. |
-bitrate <float> | Bitrate in MBit per second. Default: 4.0. |
-end <int> | End frame. Default: Last image file. |
-flip <bool> | Flip images. Default: false. |
-format <string> | Format string for "image create photo" command. Default: None. Example: -format "raw -map minmax". |
-fps <int> | Frames per second. Default: 25. |
-start <int> | Start frame. Default: First image file. |
-verbose <int> | Print verbose messages. Default: No. No: 0. Once: 1. Per image: 2. |
Description
Note, that options -start
and -end
refer either to the number in the file pattern or the range of the file list. In the latter case note that the first list index is zero.
See also
proc ::mawt::VideoImport {imgFilePattern movieFile args} { # Generate a video by importing a series of image files. # # imgFilePattern - Pattern for image input files or a list of image input files. # If file pattern, the file names must contain a printf like # integer format specifier. # movieFile - Movie output file name. # args - Options described below. # # -start <int> - Start frame. Default: First image file. # -end <int> - End frame. Default: Last image file. # -format <string> - Format string for "image create photo" command. Default: None. # Example: -format "raw -map minmax". # -fps <int> - Frames per second. Default: 25. # -bitrate <float> - Bitrate in MBit per second. Default: 4.0. # -flip <bool> - Flip images. Default: false. # -verbose <int> - Print verbose messages. Default: No. # No: 0. Once: 1. Per image: 2. # # Note, that options `-start` and `-end` refer either to the number in the file pattern or # the range of the file list. In the latter case note that the first list index is zero. # # See also: VideoExport set startFrame -1 set endFrame -1 set flip 0 set verbose 0 set format "" foreach { key value } $args { switch -exact $key { "-start" { set startFrame [expr {int($value)}] } "-end" { set endFrame [expr {int($value)}] } "-format" { set format $value } "-flip" { set flip [expr {bool($value)}] } "-verbose" { set verbose [expr {int($value)}] } } } if { $startFrame < 0 } { set startFrame 0 } if { [llength $imgFilePattern] > 1 } { if { $endFrame < 0 } { set endFrame [expr {[llength $imgFilePattern] - 1}] } set imgFileList [lrange $imgFilePattern $startFrame $endFrame] } else { set inFileName [format $imgFilePattern $startFrame] if { ! [file exists $inFileName] } { error "Image file $inFileName does not exist." } if { $endFrame < 0 } { for { set i $startFrame } { true } { incr i } { set inFileName [format $imgFilePattern $i] if { ! [file exists $inFileName] } { set endFrame [expr {$i -1}] break } lappend imgFileList $inFileName } } else { for { set i $startFrame } { $i <= $endFrame } { incr i } { set inFileName [format $imgFilePattern $i] if { ! [file exists $inFileName] } { error "Image file $inFileName does not exist." } lappend imgFileList $inFileName } } } if { $verbose >= 1 } { if { [llength $imgFilePattern] > 1 } { puts "Input files : List of [llength $imgFilePattern] files" } else { puts "Input files : $imgFilePattern" } puts "Start : $startFrame" puts "End : $endFrame" puts "Image format: $format" puts "Output file : $movieFile" } set numImportedImgs 0 foreach inFileName $imgFileList { if { $verbose >= 2 } { puts [format " %4d of %4d: Reading image $inFileName ..." [expr $numImportedImgs + 1] [expr {$endFrame - $startFrame + 1}]] } if { $format eq "" } { set phImg [image create photo -file $inFileName] } else { set phImg [image create photo -file $inFileName -format "$format"] } set w [image width $phImg] set h [image height $phImg] if { ! [info exists videoObj] } { set videoObj [mawt Video new $movieFile "w" -width $w -height $h {*}$args] set vectorObj [mawt Vector new [expr {$w * $h * 3}]] } $vectorObj FromPhoto $phImg 3 1 0 image delete $phImg $videoObj WriteNextImage [$vectorObj Get] $w $h $flip incr numImportedImgs } if { $numImportedImgs > 0 } { $videoObj Close $vectorObj destroy $videoObj destroy } if { $verbose >= 2 } { puts "Finishing video $movieFile" } return $numImportedImgs }
Classesmawt, Top
Vector [::mawt]mawt, Top
Method summary
constructor | Constructor for the class. |
destructor | Destructor for the class. |
FromByteArray | Create a Vector from a binary string. |
FromPhoto | Not documented. |
Get | Not documented. |
ToByteArray | Copy a Vector into a binary string. |
ToPhoto | Not documented. |
constructor [::mawt::Vector]Vector, Top
Vector new numBytes
Parameters
numBytes | Not documented. |
method constructor {numBytes} { if { $numBytes > 0 } { set mVec [mawt::new_UByte $numBytes] } }
destructor [::mawt::Vector]Vector, Top
method destructor {} { mawt::delete_UByte $mVec }
FromByteArray [::mawt::Vector]Vector, Top
Create a Vector from a binary string.
Parameters
str | Binary string. |
Description
Create a new Vector from given binary string $str
.
See also
method FromByteArray {str} { # Create a Vector from a binary string. # # str - Binary string. # # Create a new Vector from given binary string $str. # # See also: ToByteArray set numBytes [string length $str] if { $numBytes == 0 } { error "String has zero length" } set mVec [mawt::new_UByte $numBytes] mawt::VectorFromByteArray $str $mVec $numBytes 0 0 }
FromPhoto [::mawt::Vector]Vector, Top
Parameters
phImg | Not documented. |
numChans | Not documented. |
scale | Not documented. |
offset | Not documented. |
method FromPhoto {phImg numChans scale offset} { return [mawt::VectorFromPhoto $phImg $mVec $numChans $scale $offset] }
Get [::mawt::Vector]Vector, Top
method Get {} { return $mVec }
ToByteArray [::mawt::Vector]Vector, Top
Copy a Vector into a binary string.
Parameters
numBytes | int |
srcOff | int Optional, default 0 . |
destOff | int Optional, default 0 . |
Description
Copy $numBytes
elements into a Tcl binary string and return that string. $srcOff
and $destOff
may be used optionally to specify an offset into the source and the destination.
See also
method ToByteArray {numBytes {srcOff 0} {destOff 0}} { # Copy a Vector into a binary string. # # numBytes - int # srcOff - int # destOff - int # # Copy $numBytes elements into a Tcl binary string and return that string. # $srcOff and $destOff may be used optionally to specify # an offset into the source and the destination. # # See also: FromByteArray if { $numBytes == 0 } { error "Vector has zero length" } # First generate a binary string of appropriate size. set bytes [binary format a$numBytes 0] mawt::VectorToByteArray $mVec $bytes $numBytes $srcOff $destOff return $bytes }
ToPhoto [::mawt::Vector]Vector, Top
Parameters
phImg | Not documented. |
width | Not documented. |
height | Not documented. |
numChans | Not documented. Optional, default 3 . |
linesAreBottomUp | Not documented. Optional, default 0 . |
method ToPhoto {phImg width height {numChans 3} {linesAreBottomUp 0}} { mawt::VectorToPhoto $mVec $phImg $width $height $numChans $linesAreBottomUp }
Video [::mawt]mawt, Top
Method summary
constructor | Constructor for the class. |
destructor | Destructor for the class. |
Close | Close a video stream. |
Create | Create a new empty video file. |
GetDuration | Get video duration information as a dict. |
GetDurationAsString | Get video duration information as a string. |
GetFramerate | Not documented. |
GetHeight | Get the height of a video stream. |
GetImage | Get an image from a video stream. |
GetNextImage | Get next image from a video stream. |
GetNumFrames | Not documented. |
GetWidth | Get the width of a video stream. |
IsOpen | Not documented. |
Lock | Lock a video stream. |
Open | Open a video file. |
Start | Start acquisition of a video stream. |
Stop | Stop acquisition of a video stream. |
Unlock | Unlock a video stream. |
WriteNextImage | Write next image to a video stream. |
WriteNextPhotoImage | Write next photo image to a video stream. |
constructor [::mawt::Video]Video, Top
Video new fileName mode ?args?
Parameters
fileName | Not documented. |
mode | Not documented. |
method constructor {fileName mode args} { set mVideoFile "" set mVideoId "NULL" set mNumBytes -1 set width 256 set height 256 set fps 25 set bitrate 4.0 foreach { key value } $args { switch -exact $key { "-width" { set width [expr {int($value)}] } "-height" { set height [expr {int($value)}] } "-fps" { set fps [expr {int($value)}] } "-bitrate" { set bitrate [expr {double($value)}] } } } if { $mode eq "r" } { my Open $fileName } else { my Create $fileName $width $height $fps $bitrate } set mMode $mode }
destructor [::mawt::Video]Video, Top
method destructor {} { if { [my IsOpen] } { my Close } }
Close [::mawt::Video]Video, Top
Close a video stream.
See also
method Close {} { # Close a video stream. # # See also: Open if { $mMode eq "r" } { mawt::MawtVideoClose $mVideoId } else { if {! [mawt::MawtVideoFinish $mVideoId] } { throw [list Video Close] [mawt::MawtGetErrorMessage] } } set mVideoId "NULL" set mVideoFile "" }
Create [::mawt::Video]Video, Top
Create a new empty video file.
Parameters
fileName | Create the video stream in specified file. |
width | Width of the video stream. |
height | Height of the video stream. |
fps | Framerate of the video streams (frames per second). |
bitrate | Not documented. |
birate | Bit rate of the video ostream in MBits/s. |
Description
Throws an error, if the file could not be openend.
See also
Close, WriteNextImage, WriteNextPhotoImage
method Create {fileName width height fps bitrate} { # Create a new empty video file. # # fileName - Create the video stream in specified file. # width - Width of the video stream. # height - Height of the video stream. # fps - Framerate of the video streams (frames per second). # birate - Bit rate of the video ostream in MBits/s. # # Throws an error, if the file could not be openend. # # See also: Close WriteNextImage WriteNextPhotoImage if { [my IsOpen] } { my Close } set mVideoId [mawt::MawtVideoCreate $fileName $width $height $fps $bitrate] if { ! [my IsOpen] } { throw [list Video Create] [mawt::MawtGetErrorMessage] } set mVideoFile $fileName }
GetDuration [::mawt::Video]Video, Top
Get video duration information as a dict.
Description
Get the duration of current video stream. The duration is returned as a dictionary with the keys: minutes
, seconds
, frames
.
See also
method GetDuration {} { # Get video duration information as a dict. # # Get the duration of current video stream. # The duration is returned as a dictionary with the # keys: `minutes`, `seconds`, `frames`. # # See also: GetDurationAsString set numFrames [mawt::MawtVideoGetNumFrames $mVideoId] set frameRate [expr int([mawt::MawtVideoGetFramerate $mVideoId] + 0.5)] set secs [expr $numFrames / $frameRate] dict set durDict minutes [expr {$secs / 60}] dict set durDict seconds [expr {$secs - [dict get $durDict minutes] * 60}] dict set durDict frames [expr {$numFrames % $frameRate}] return $durDict }
GetDurationAsString [::mawt::Video]Video, Top
Get video duration information as a string.
Description
Get the duration of current video stream. The duration is returned as a string in the following format: minutes:seconds.frames
.
See also
method GetDurationAsString {} { # Get video duration information as a string. # # Get the duration of current video stream. # The duration is returned as a string in the following # format: `minutes:seconds.frames`. # # See also: GetDuration set durDict [my GetDuration] return [format "%02d:%02d.%02d" [dict get $durDict minutes] [dict get $durDict seconds] [dict get $durDict frames] ] }
GetFramerate [::mawt::Video]Video, Top
method GetFramerate {} { return [mawt::MawtVideoGetFramerate $mVideoId] }
GetHeight [::mawt::Video]Video, Top
Get the height of a video stream.
Return value
Returns the height of a video stream in pixels.
See also
method GetHeight {} { # Get the height of a video stream. # # Returns the height of a video stream in pixels. # # See also: Open GetWidth return [mawt::MawtVideoGetHeight $mVideoId] }
GetImage [::mawt::Video]Video, Top
Get an image from a video stream.
Parameters
img | A Vector of appropriate size to store the image data. |
flip | Boolean value to specify image flipping. |
num | Image number as integer value starting at zero. |
Description
Get image $num
from current video stream. The image will be stored in variable $img
. $img
must point to a buffer of appropriate size. If $flip
is set to true, the image is returned in bottom-up scanline order as needed by OpenGL. If $flip
is set to false, the image is returned in top-down scanline order as needed by the img::raw extension.
Throws an error, if the image could not be retrieved from the video stream.
See also
Open, GetNextImage, GetWidth, GetHeight
method GetImage {img flip num} { # Get an image from a video stream. # # img - A Vector of appropriate size to store the image data. # flip - Boolean value to specify image flipping. # num - Image number as integer value starting at zero. # # Get image $num from current video stream. # The image will be stored in variable $img. # $img must point to a buffer of appropriate size. # If $flip is set to true, the image is returned in # bottom-up scanline order as needed by OpenGL. # If $flip is set to false, the image is returned in # top-down scanline order as needed by the img::raw extension. # # Throws an error, if the image could not be retrieved # from the video stream. # # See also: Open GetNextImage GetWidth GetHeight if { ! [mawt::MawtVideoGetImage $mVideoId $img [expr {bool($flip)}] $num] } { throw [list Video GetImage] [mawt::MawtGetErrorMessage] } }
GetNextImage [::mawt::Video]Video, Top
Get next image from a video stream.
Parameters
img | A Vector of appropriate size to store the image data. |
flip | Boolean value to specify image flipping. |
Description
Get the next image from current video stream. The image will be stored in variable $img
. $img
must point to a buffer of appropriate size. If $flip
is set to true, the image is returned in bottom-up scanline order as needed by OpenGL. If $flip
is set to false, the image is returned in top-down scanline order as needed by the img::raw extension.
Throws an error, if the image could not be retrieved from the video stream.
See also
Open, Close, GetImage, GetWidth, GetHeight
method GetNextImage {img flip} { # Get next image from a video stream. # # img - A Vector of appropriate size to store the image data. # flip - Boolean value to specify image flipping. # # Get the next image from current video stream. # The image will be stored in variable $img. # $img must point to a buffer of appropriate size. # If $flip is set to true, the image is returned in # bottom-up scanline order as needed by OpenGL. # If $flip is set to false, the image is returned in # top-down scanline order as needed by the img::raw extension. # # Throws an error, if the image could not be retrieved # from the video stream. # # See also: Open Close GetImage GetWidth GetHeight if { ! [mawt::MawtVideoGetNextImage $mVideoId $img [expr {bool($flip)}]] } { # TODO: Check why this throws an error at the last frame. # throw [list Video GetNextImage] [mawt::MawtGetErrorMessage] } }
GetNumFrames [::mawt::Video]Video, Top
method GetNumFrames {} { return [mawt::MawtVideoGetNumFrames $mVideoId] }
GetWidth [::mawt::Video]Video, Top
Get the width of a video stream.
Return value
Returns the width of a video stream in pixels.
See also
method GetWidth {} { # Get the width of a video stream. # # Returns the width of a video stream in pixels. # # See also: Open GetHeight return [mawt::MawtVideoGetWidth $mVideoId] }
IsOpen [::mawt::Video]Video, Top
method IsOpen {} { if { $mVideoId ne "NULL" } { return true } else { return false } }
Lock [::mawt::Video]Video, Top
Lock a video stream.
See also
method Lock {} { # Lock a video stream. # # See also: Open Unlock mawt::MawtVideoLock $mVideoId }
Open [::mawt::Video]Video, Top
Open a video file.
Parameters
fileName | Open the video stream stored in specified file. |
Description
If a video stream is already open, it is closed before opening the new video stream.
Throws an error, if the file could not be openend.
See also
method Open {fileName} { # Open a video file. # # fileName - Open the video stream stored in specified file. # # If a video stream is already open, it is closed before opening # the new video stream. # # Throws an error, if the file could not be openend. # # See also: Close Start Stop if { [my IsOpen] } { my Close } set mVideoId [mawt::MawtVideoOpen $fileName] if { ! [my IsOpen] } { throw [list Video Open] [mawt::MawtGetErrorMessage] } set mVideoFile $fileName }
Start [::mawt::Video]Video, Top
Start acquisition of a video stream.
Parameters
width | integer Optional, default -1 . |
height | integer Optional, default -1 . |
Description
Start acquisition of current video stream. If $width
and $height
are specified and greater than zero, stretch the video to that size. Otherwise the video is played in its original size.
Return value
Returns the number of bytes needed for a video frame. If the video could not be started, an error is thrown.
See also
method Start {{width -1} {height -1}} { # Start acquisition of a video stream. # # width - integer # height - integer # # Start acquisition of current video stream. # If $width and $height are specified and greater than # zero, stretch the video to that size. # Otherwise the video is played in its original size. # # Returns the number of bytes needed for a video frame. # If the video could not be started, an error is thrown. # # See also: Open Stop set mNumBytes [mawt::MawtVideoStart $mVideoId $width $height] if { $mNumBytes < 0 } { throw [list Video Start] [mawt::MawtGetErrorMessage] } return $mNumBytes }
Stop [::mawt::Video]Video, Top
Stop acquisition of a video stream.
See also
method Stop {} { # Stop acquisition of a video stream. # # See also: Start Open Close mawt::MawtVideoStop $mVideoId }
Unlock [::mawt::Video]Video, Top
Unlock a video stream.
See also
method Unlock {} { # Unlock a video stream. # # See also: Open Lock mawt::MawtVideoUnlock $mVideoId }
WriteNextImage [::mawt::Video]Video, Top
Write next image to a video stream.
Parameters
img | A Vector containing the image data. |
width | Width of the image. |
height | Height of the image. |
flip | Boolean value to specify image flipping. |
Description
Write the next image to the current video stream.
The image data must be available in variable $img
. $img
must point to a buffer of size width by height. If $flip
is set to true, the image is returned in bottom-up scanline order as needed by OpenGL. If $flip
is set to false, the image is returned in top-down scanline order as needed by the img::raw extension.
Throws an error, if the image could not be written to the video stream.
See also
WriteNextPhotoImage, Create, Close, GetImage, GetWidth, GetHeight
method WriteNextImage {img width height flip} { # Write next image to a video stream. # # img - A Vector containing the image data. # width - Width of the image. # height - Height of the image. # flip - Boolean value to specify image flipping. # # Write the next image to the current video stream. # # The image data must be available in variable $img. # $img must point to a buffer of size width by height. # If $flip is set to true, the image is returned in # bottom-up scanline order as needed by OpenGL. # If $flip is set to false, the image is returned in # top-down scanline order as needed by the img::raw extension. # # Throws an error, if the image could not be written # to the video stream. # # See also: WriteNextPhotoImage Create Close GetImage GetWidth GetHeight if { ! [mawt::MawtVideoWriteNextImage $mVideoId $img $width $height [expr {bool($flip)}]] } { # TODO: Check why this throws an error at the last frame. # throw [list Video WriteNextImage] [mawt::MawtGetErrorMessage] } }
WriteNextPhotoImage [::mawt::Video]Video, Top
Write next photo image to a video stream.
Parameters
phImg | A Tk photo image. |
flip | Boolean value to specify image flipping. |
Description
The image data must be available in photo image $phImg
.
If $flip
is set to true, the image is returned in bottom-up scanline order as needed by OpenGL. If $flip
is set to false, the image is returned in top-down scanline order as needed by the img::raw extension.
Throws an error, if the image could not be written to the video stream.
See also
WriteNextImage, Create, Close, GetImage, GetWidth, GetHeight
method WriteNextPhotoImage {phImg flip} { # Write next photo image to a video stream. # # phImg - A Tk photo image. # flip - Boolean value to specify image flipping. # # The image data must be available in photo image $phImg. # # If $flip is set to true, the image is returned in # bottom-up scanline order as needed by OpenGL. # If $flip is set to false, the image is returned in # top-down scanline order as needed by the img::raw extension. # # Throws an error, if the image could not be written # to the video stream. # # See also: WriteNextImage Create Close GetImage GetWidth GetHeight set w [image width $phImg] set h [image height $phImg] set vectorObj [mawt Vector new [expr {$w * $h * 3}]] $vectorObj FromPhoto $phImg 3 1 0 if { ! [mawt::MawtVideoWriteNextImage $mVideoId [$vectorObj Get] $w $h [expr {bool($flip)}]] } { # TODO: Check why this throws an error at the last frame. # throw [list Video WriteNextImage] [mawt::MawtGetErrorMessage] } $vectorObj destroy }