Wiretap API - create clip help needed

Hi guys,

It seem to be another quite rare case but I’m trying to use wiretap api for the next verson of TimewarpML in order to avoid exporting sequences and importing it back.
I can read image data well but really struggle to create correct buffer in order to write one.

I do have a little code snippet that should create an 8-bit red square:

import os
import sys

from adsk.libwiretapPythonClientAPI import WireTapClient
from adsk.libwiretapPythonClientAPI import WireTapServerHandle
from adsk.libwiretapPythonClientAPI import WireTapNodeHandle
from adsk.libwiretapPythonClientAPI import WireTapStr
from adsk.libwiretapPythonClientAPI import WireTapInt
from adsk.libwiretapPythonClientAPI import WireTapClipFormat

import ctypes
import flame

# assuming you have numpy unpacked in /var/tmp/numpy
# one can just unzip wheel

sys.path.insert(0, '/var/tmp/numpy')
import numpy as np
del sys.path[0]

python_api = ctypes.CDLL(sys.executable)
python_api.PyUnicode_FromKindAndData.argtypes = [ctypes.c_int, ctypes.c_char_p, ctypes.c_ssize_t]
python_api.PyUnicode_FromKindAndData.restype = ctypes.py_object

class WireTapException(Exception):
    def __init__(self, msg):
        flame.messages.show_in_dialog(
            title = 'flameTimewrarpML',
            message = msg,
            type = 'error',
            buttons = ['Ok']
        )

server_handle = WireTapServerHandle('localhost')

num_frames = 4

library = flame.projects.current_project.create_shared_library('twml')
parent_node_handle = WireTapNodeHandle(server_handle, flame.PyClip.get_wiretap_node_id(library))

new_clip_node_handle = WireTapNodeHandle()
clip_format = WireTapClipFormat(
    24,
    24,  # width, height
    3 * 8,  # bits per pixel
    3,  # number of channels
    24,  # frame rate
    1,  # pixel ratio
    WireTapClipFormat.ScanFormat.SCAN_FORMAT_PROGRESSIVE,
    WireTapClipFormat.FORMAT_RGB(),
)

if not parent_node_handle.createClipNode(
    "MyNewClip",  # display name
    clip_format,  # clip format
    "CLIP",  # extended (server-specific) type
    new_clip_node_handle,  # created node returned here
):
    raise WireTapException(
        "Unable to create clip node: %s." % parent_node_handle.lastError()
    )

if not new_clip_node_handle.setNumFrames(int(num_frames)):
    raise WireTapException(
        "Unable to set the number of frames: %s." % new_clip_node_handle.lastError()
    )

new_fmt = WireTapClipFormat()
if not new_clip_node_handle.getClipFormat(new_fmt):
    raise WireTapException(
        "Unable to obtain clip format: %s." % new_clip_node_handle.lastError()
    )

# array of red
pattern = np.array([0xff, 0x00, 0x00], dtype=np.uint8)
repeated_array = np.tile(pattern, new_fmt.frameBufferSize() // len(pattern))
remainder = new_fmt.frameBufferSize() % len(pattern)
if remainder > 0:
    arr = np.concatenate([repeated_array,
                            np.zeros(remainder, dtype=np.uint8)])


for frame_number in range(0, num_frames):

    # method 1
    buff_out = str(arr.tobytes(), 'latin-1')
    # method 2
    buff_out = python_api.PyUnicode_FromKindAndData(ctypes.c_int(1), arr.tobytes(), arr.nbytes)

    print (":".join("{:02x}".format(ord(c)) for c in buff_out))

    if not new_clip_node_handle.writeFrame(frame_number, buff_out, new_fmt.frameBufferSize()):
        raise WireTapException(
            "Unable to obtain write frame %i: %s."
            % (frame_number, new_clip_node_handle.lastError())
        )
    print("Successfully wrote frame %i." % frame_number)

And I’m getting quite interesting clip instead:

Screenshot 2023-05-24 at 01.28.59

you can check it out assuming you have numpy installed or unpacked somewhere.

Giving it a buffer read from another clip works just well, but I need to be able to write an amended image data here.

Any ideas and help are greatly appreciated!

Thank you
Andriy,

Eventually the only workaround here I could find was to save the image data into an image file and then use gateway server handle in order to read it back to a frame buffer and then save it to and actual clip. It is a bit silly but seem to work for now though might need a bit wider testing.

the code loos something like this:

                gateway_server_id = WireTapServerId("Gateway", "localhost")
                gateway_server_handle = WireTapServerHandle(gateway_server_id)
                clip_node_handle = WireTapNodeHandle(gateway_server_handle, file_path + '@CLIP')
                fmt = WireTapClipFormat()
                if not clip_node_handle.getClipFormat(fmt):
                    raise Exception("Unable to obtain clip format: %s." % clip_node_handle.lastError())
                
                buff = "0" * fmt.frameBufferSize()

                if not clip_node_handle.readFrame(0, buff, fmt.frameBufferSize()):
                    raise Exception(
                        'Unable to obtain read frame %i: %s.' % (frame_number, clip_node_handle.lastError())
                    )
                
                server_handle = WireTapServerHandle('localhost')
                destination_node_handle = WireTapNodeHandle(server_handle, self.destination_node_id)
                dest_fmt = WireTapClipFormat()
                if not destination_node_handle.getClipFormat(dest_fmt):
                    raise Exception('Unable to obtain clip format: %s.' % clip_node_handle.lastError())

                if not destination_node_handle.writeFrame(
                    frame_number, buff, dest_fmt.frameBufferSize()
                ):
                    raise Exception(
                        "Unable to obtain write frame %i: %s."
                        % (frame_number, destination_node_handle.lastError())
                    )

                os.remove(file_path)

Reviving this in 2026. Can someone help me with a simple bit of python commented with how to use the wiretap API’s create clip?

No matter what I do I’m getting read-only errors and I’m pulling my hair out.

Simplified:

 # 1. Build format                                                                                                                                                                                                                                                                  
  fmt = WireTapClipFormat()                                                                                                                                                                                                                                                          
  fmt.setWidth(5792)                                                                                                                                                                                                                                                                 
  fmt.setHeight(4854)                                                                                                                                                                                                                                                                
  fmt.setNumChannels(3)
  fmt.setBitsPerPixel(96)       # 32-bit * 3
  fmt.setFrameRate(24.0)
  fmt.setScanFormat(0)           # progressive
  fmt.setPixelRatio(1.0)

  # 2. Connect to server
  server = WireTapServerHandle(WireTapServerId("IFFFS", "flame-01"))

  # 3. Get parent reel handle
  parent = WireTapNodeHandle(server, "/projects/cf39.../128900c0_699d3575_0004c38e")

  # 4. Create clip — THIS FAILS: "Node is read only"
  new_handle = WireTapNodeHandle()
  parent.createClipNode("output", fmt, "CLIP", new_handle)

The createClipNode call is where it dies. Is there a different API call or argument that might work? Maybe the node type string should be something other than “CLIP”, or maybe Flame needs a specific format tag set on the WireTapClipFormat? @fredwarren ?

@cnoellert The problem is that the node is read only. It is hard to tell why just by looking at your code, but it might be because:

  1. The parent is not the one you think it is or it is a place that cannot hold a clip like a workspace or a desktop.
  2. You are using a Wiretap SDK that does not match the Flame version you are using.

Hey Fred–thanks for the quick response. Here’s where I am at this point.

SDK/Flame version match is confirmed:

  • Server reports version 2026.2 via getVersion()
  • Flame 2026.2.1 installed on the host
  • SDK 2026.2.1 on the client
  • Same results with both 2025.2.2 and 2026.2.1 SDK libraries
  • Tested via both the Python SDK and the C++ CLI tools (wiretap_create_clip, wiretap_can_create_node) — identical results

Parent node verification:
Verified every node in the path using wiretap_get_display_name and wiretap_get_node_type. The target is confirmed as a REEL. I also tested canCreateNode -t CLIP against every node type in the project — REELs, LIBRARYs, LIBRARY_LISTs, REEL_GROUPs — all return “can NOT
create.” The entire project is read-only.

Here’s the interesting bit:

  • A freshly created project (via wiretap_create_node -t PROJECT) allows the full chain: create LIBRARY → REEL → CLIP → writeFrame. Everything works perfectly.
  • Any project that has been previously opened in Flame returns “Node is read only” (ifffsWTEntryMgr.C:1154) on all internal nodes — even with Flame completely shut down.
  • This reproduces on both localhost and remote IFFFS servers.
  • The IFFFS server itself is not globally read-only — canCreateNode -n /projects -t PROJECT returns “can create.”

It seems like Flame sets some persistent state on the project’s IFFFS entries when it opens a project, and that state is never cleared — making the project permanently read-only to external Wiretap clients. Is there a step I’m missing to “open” or “unlock” a project for
external write access? I’ve tested both locally on a Mac and with a remote linux host and have the same errors/oddities on both.

For context, I’m building a ComfyUI integration that uses Wiretap to grab clips from Flame, processes them, and write results back. The read path works great via wiretap_rw_frame… I just need to close the write loop and stop the bleeding.

@fredwarren Also for context, here’s a dump of the project created on the Commandline called comfy versus a project I’m trying to write to which is the arc-nfc project. The first one works, the second one doesn’t:

The problem is that Wiretap cannot write in a Workspace currently opened in Flame. You can try to go through a Shared Library to do so.

@fredwarren Yeah, that’s what I’m doing. The flame project I created on the command line writes clips to the shared library no problem. In fact I can create reels and shared libraries in addition to clips no problem. The issue seems to be that once a Workspace is created it’s locking the shared libraries, even when Flame isn’t running that project or even running at all.

So in the case of that working flame project that I created from the command line–once I open Flame into that project, Flame no longer allows me to create any objects in the shared libraries via WT. If I close it, it stays read only. I quit Flame and it stays read-only. Once there’s a workspace, it seems to be game over.

Son of a bitch. The fix is one line: os.umask(0) before initializing the Wiretap client.

Days like this make me feel small.

Omg