Search code examples
pythonwebrtcrtcdatachannelaiortc

Send and receive objects through WebRTC data channel


In my project, I am using WebRTC to connect between 2 client using the aiortc package.

I am using this example code and it works, but it seems I can't send non-string data in the data channel.

This is what I send in the data channel (modified the code in the start function in client.js file):

dc.onopen = function() {
    dataChannelLog.textContent += '- open\n';
    dcInterval = setInterval(function() {
        let message = new DataObject(/*All the parameters*/);
        dataChannelLog.textContent += '> ' + message + '\n';
        dc.send(message);
    }, 100);
};

Where DataObject is a class I created that contains the data I want to send.

The Python client receives [object Object] as a string. I expected it will send the bytes representing the object that I can convert back in Python to a normal class.

I know that a workaround for this is to convert the object to a string-format (like JSON), but I prefer not to do it because I am sending the objects very frequently (and every object contains a large array in it) and I am sure it will lead to a performance issues.

So my question is, how can I send the object through the data channel without converting to a string¿

EDIT: If it helps, I can use an array instead of an object to represent my data. But again, it is still sent and received as a string.


Solution

  • Thanks o-jones for the detailed answer.

    In my case it was fairly simple, because I was able to represent all my data as an array.

    The main issue I had is that I didn't know the send function has an "overload" that accepts bytes array

    After realizing that, I created a Float32Array in Javascript to hold my data and send it.

    And in the Python side, I read this data and converted it to a float array using struct.unpack function.

    Something like that:

    Javascript side:

    dc.onopen = function() {
        dataChannelLog.textContent += '- open\n';
        dcInterval = setInterval(function() {
            let dataObj = new DataObject(/*All the parameters*/);
            let data = new Float32Array(3); // Build an array (in my case 3 floats array)
    
            // Insert the data into the array
            data[0] = dataObj.value1;
            data[1] = dataObj.value2;
            data[2] = dataObj.value3;
    
            // Send the data
            dc.send(data);
        }, 100);
    };
    

    Python side:

    import struct
    
    def message_received(message: str | bytes) -> None:
        if isinstance(message, str):
            return  # Don't handle string messages
    
        # Read 3 floats from the bytes array we received.
        data = struct.unpack('3f', message)