createSendTransport function
- CreateSendTransportOptions options
Creates a WebRTC send transport for media transmission (audio, video, or screen).
This function initiates a WebRTC send transport with a server for sending media streams (audio, video, screen). It performs the following actions:
- Emits a
createWebRtcTransport
event to the server to request the creation of a WebRTC transport. - Sets up a transport to handle events for connecting, producing, and monitoring connection state changes.
- Calls
connectSendTransport
for further media setup and transmission.
Parameters:
options
(CreateSendTransportOptions
): Contains the option specifying the media type ('audio', 'video', 'screen', or 'all') and the parameters required for transport creation.
Logic Flow:
- Emit
createWebRtcTransport
Event:- Requests a WebRTC transport from the server.
- Waits for an acknowledgment from the server containing transport parameters or an error response.
- Transport Setup:
- Creates the send transport with callbacks for producer updates.
- Sets up
connect
,produce
, andconnectionstatechange
events on the transport.connect
: Completes the DTLS connection by sending DTLS parameters to the server.produce
: Initiates media transmission by sending RTP parameters and additional data to the server.connectionstatechange
: Monitors the transport’s state, handling any failures.
- Invoke
connectSendTransport
:- Calls
connectSendTransport
to finalize and manage ongoing media transmission based on the selected option.
- Calls
Callbacks:
- Producer Callback: Selects the appropriate producer (audio, video, or screen) for the current transport session.
- Connection Events: Sets up handlers for connection, media production, and connection state changes.
Throws:
- Logs an error if transport creation fails at any stage.
Example Usage:
final options = CreateSendTransportOptions(
option: 'video',
parameters: MyCreateSendTransportParameters(
islevel: '2',
member: 'user123',
socket: mySocket,
localSocket: myLocalSocket,
device: myDevice,
transportCreated: false,
updateProducerTransport: (transport) => print('Producer Transport updated'),
updateTransportCreated: (created) => print('Transport created: $created'),
updateScreenProducer: (producer) => print('Screen Producer updated'),
updateAudioProducer: (producer) => print('Audio Producer updated'),
updateVideoProducer: (producer) => print('Video Producer updated'),
connectSendTransport: connectSendTransport,
),
);
createSendTransport(options).then((_) {
print('Send transport created successfully.');
}).catchError((error) {
print('Error creating send transport: $error');
});
Notes:
- This function relies on socket-based communication with the server to manage transport creation and media production.
- Specific callback functions for updating producers (audio, video, screen) allow flexible media handling.
Implementation
Future<void> createSendTransport(
CreateSendTransportOptions options,
) async {
try {
// Destructure parameters from the options
final parameters = options.parameters;
String islevel = parameters.islevel;
String member = parameters.member;
io.Socket? socket = parameters.socket;
Device? device = parameters.device;
bool transportCreated = parameters.transportCreated;
Transport? producerTransport = parameters.producerTransport;
// Callback functions from parameters
final updateProducerTransport = parameters.updateProducerTransport;
final updateTransportCreated = parameters.updateTransportCreated;
final updateScreenProducer = parameters.updateScreenProducer;
final updateAudioProducer = parameters.updateAudioProducer;
final updateVideoProducer = parameters.updateVideoProducer;
final connectSendTransport = parameters.connectSendTransport;
// Get updated device and socket parameters if necessary
final updatedParams = parameters.getUpdatedAllParams();
device = updatedParams.device;
socket = updatedParams.socket;
// Create local send transport first
try {
await createLocalSendTransport(options);
} catch (error) {
if (kDebugMode) {
print("Error creating local send transport: $error");
}
}
// Emit 'createWebRtcTransport' event to the server
Completer<Map<String, dynamic>> producerCompleter = Completer();
socket!.emitWithAck(
'createWebRtcTransport',
{'consumer': false, 'islevel': islevel},
ack: (response) async {
if (response['error'] != null) {
producerCompleter.completeError(response['error']);
} else {
producerCompleter.complete(response['params']);
}
Map<String, dynamic> webrtcTransportMap =
await producerCompleter.future;
//producer callback function
void producerCallbackFunction(Producer producer) {
producer.kind == 'video' && producer.source == 'screen'
? updateScreenProducer(producer)
: producer.kind == 'audio'
? updateAudioProducer(producer)
: updateVideoProducer(producer);
}
try {
// Create a WebRTC send transport
producerTransport = device?.createSendTransportFromMap(
webrtcTransportMap,
producerCallback: producerCallbackFunction,
);
} catch (error) {
if (kDebugMode) {
print('MediaSFU - Error creating send transport: $error');
}
}
updateProducerTransport(producerTransport);
// Handle 'connect' event for DTLS connection
producerTransport?.on('connect', (data) async {
try {
socket!.emit('transport-connect',
{'dtlsParameters': data['dtlsParameters'].toMap()});
data['callback']();
} catch (error) {
data['errback'](error);
}
});
// Handle 'produce' event to initiate media transmission
producerTransport?.on('produce', (data) async {
try {
socket!.emitWithAck('transport-produce', {
'kind': data['kind'],
'rtpParameters': data['rtpParameters'].toMap(),
if (data['appData'] != null)
'appData': Map<String, dynamic>.from(data['appData']),
'islevel': islevel,
'name': member,
}, ack: (response) async {
data['callback'](response['id']);
});
} catch (error) {
data['errback'](error);
}
});
// Monitor the connection state and handle any failures
producerTransport?.on('connectionstatechange', (state) async {
switch (state) {
case 'connecting':
break;
case 'connected':
break;
case 'failed':
if (kDebugMode) print("Transport connection failed.");
await producerTransport?.close();
break;
default:
break;
}
});
// Set transport as created and invoke connectSendTransport
transportCreated = true;
updateTransportCreated(transportCreated);
try {
parameters.updateProducerTransport(producerTransport);
final optionsConnect = ConnectSendTransportOptions(
targetOption: 'remote',
option: options.option,
parameters: parameters,
audioConstraints: options.audioConstraints,
videoConstraints: options.videoConstraints,
);
await connectSendTransport(
optionsConnect,
);
} catch (error) {
if (kDebugMode) {
print("Error in transport creation: $error");
}
}
},
);
} catch (error) {
if (kDebugMode) {
print('MediaSFU - Error creating send transport: $error');
}
}
}