- language:python - sdk:compatibility - product:voice # Updating Conference Recordings in SignalWire ## **Overview** When managing conference calls using SignalWire, its sometimes necessary to pause and resume call recordings dynamically. This guide offers an in-depth look into how to update active conference recordings utilizing the SignalWire REST Client Python SDK as well as SignalWires REST endpoints. ## **Utilizing SignalWires REST Client SDKs** We will first cover how to accomplish updating an active conference recording utilizing the SignalWire REST Client SDK. In the below example, we will be using the Python SDK, along with Ngrok and Flask to help our server. [Compatibility REST Client SDK](/compatibility-api/sdks). ### SignalWire Client SDK Initialization To interact with SignalWire, we start by initializing the SignalWire client SDK. This requires your SignalWire Project ID, Auth Token, and the Space URL. python from signalwire.rest import Client as SignalWireClient space_url = EXAMPLE.signalwire.com project_id = PROJECT TOKEN HERE auth_token = AUTH TOKEN HERE client = SignalWireClient(project_id, auth_token, signalwire_space_url=space_url) ### Setting Up the Conference with Detailed Callbacks When a new inbound call is made, it is directed into a conference. Alongside this, we store the details of ongoing conferences, including the recording Session ID (SID) and the recording status (whether its active or paused). Examining the conference setup: python @app.route(/inbound, methods=[POST, GET]) def inbound_call(): ... response = VoiceResponse() dial = Dial() dial.conference( name=call_sid, record=record-from-start, start_conference_on_enter=True, status_callback=f{public_url}/callback, status_callback_event=leave join, recording_status_callback=f{public_url}/store_recording_sid, recording_status_callback_event=in-progress, trim=do-not-trim ) response.append(dial) return str(response) ### Storing Conference Recording SIDs All conference information is store in a global dictionary called active_conferences. python active_conferences = {} This global dictionary will keep track of all conference_sids added to it. Once a recording has started, we will send the event back to our recording_status_callback url. The conference_sid and the recording_sid will be passed in this request as ConferenceSid and RecordingSid. Once we acquire the recording_sid we can then add it to active_conferences in the corresponding conference_sid. Additionally, we also pass a value of recording_active to keep track if that conferences recording is paused or in-progress. python @app.route(/store_recording_sid, methods=[POST, GET]) def update_recording(): conference_sid = request.form.get(ConferenceSid) recording_sid = request.form.get(RecordingSid) return 200 ### Using Callbacks to Manage Conference Recordings To update the status of a conference recording, while utilizing the SignalWire Client SDK, we will use the update method on the conference recording object. This method requires two arguments: - **pause_behavior**: This determines the behavior of the recording when paused. In this guide, we set it to skip, which means the recording will skip over the paused segment. The argument silence will allow the recording to continue, but it will remove all noise out of the recording. Both arguments will continue their behavior until the recording is continued or has ended. - **status**: This sets the recording status. It can be either paused or in-progress. Below are examples on how to use the Client SDK to update a conference recording. ##### Pausing the conference recording python recording = client.calls(conference_sid) \ .recordings(recording_sid) \ .update(status=paused, pause_behavior=skip) ##### Resuming the conference recording python recording = client.calls(conference_sid) \ .recordings(recording_sid) \ .update(status=in-progress, pause_behavior=skip) #### Dynamically Updating Recordings Base on Participant Events The actual decision to pause or resume a recording is based on the number of participants in the conference. 1. If the callback event indicates a participant has left (participant-leave) and there are fewer than 2 participants remaining, the recording is paused. 2. Conversely, if the callback event indicates a new participant has joined (participant-join) and there are more than 1 participant, the recording is resumed. Heres how this logic is implemented: python @app.route(/callback, methods=[GET, POST]) def callback(): conference_sid = request.form.get(ConferenceSid) callback_event = request.form.get(StatusCallbackEvent) recording_sid = recording_data[recording_sid] is_active = recording_data[recording_active] participants = client.conferences(conference_sid).participants.list(limit=50) if callback_event == participant-leave and len(participants) < 2: if recording_sid and is_active: client.conferences(conference_sid).recordings(recording_sid).update(pause_behavior=skip, status=paused) active_conferences[conference_sid][recording_active] = False elif callback_event == participant-join and len(participants) > 1: if recording_sid and not is_active: client.conferences(conference_sid).recordings(recording_sid).update(pause_behavior=skip, status=in-progress) active_conferences[conference_sid][recording_active] = True return 200 ### Example Script To bring everything together, heres the full script: python from flask import Flask, request, jsonify from signalwire.rest import Client as SignalWireClient from signalwire.voice_response import VoiceResponse, Dial from pyngrok import ngrok # Initialization app = Flask(__name__) space_url = EXAMPLE.signalwire.com project_id = PROJECT ID HERE auth_token = AUTH TOKEN HERE client = SignalWireClient(project_id, auth_token, signalwire_space_url=space_url) public_url = active_conferences = {} call_sid = @app.route(/inbound, methods=[POST, GET]) def inbound_call(): global call_sid call_sid = request.form.get(CallSid) response = VoiceResponse() dial = Dial() dial.conference(name=call_sid, record=record-from-start, start_conference_on_enter=True, status_callback=f{public_url}/callback, status_callback_event=leave join, recording_status_callback=f{public_url}/store_recording_sid, recording_status_callback_event=in-progress, trim=do-not-trim) response.append(dial) return str(response) @app.route(/store_recording_sid, methods=[POST, GET]) def store_recording_sid(): conference_sid = request.form.get(ConferenceSid) recording_sid = request.form.get(RecordingSid) return 200 @app.route(/callback, methods=[GET, POST]) def callback(): conference_sid = request.form.get(ConferenceSid) callback_event = request.form.get(StatusCallbackEvent) recording_sid = recording_data[recording_sid] is_active = recording_data[recording_active] participants = client.conferences(conference_sid).participants.list(limit=50) if callback_event == participant-leave and len(participants) < 2: if recording_sid and is_active: client.conferences(conference_sid).recordings(recording_sid).update(pause_behavior=skip, status=paused) active_conferences[conference_sid][recording_active] = False elif callback_event == participant-join and len(participants) > 1: if recording_sid and not is_active: client.conferences(conference_sid).recordings(recording_sid).update(pause_behavior=skip, status=in-progress) active_conferences[conference_sid][recording_active] = True return 200 if __name__ == __main__: public_url = ngrok.connect(5000).public_url print(fWebhook is live at {public_url}) app.run(port=5000) ## **Utilizing SignalWires Compatibility REST API** The REST API provides a way for developers to interact with SignalWire services without needing to use the SDKs. This is particularly useful for platforms or situations where an SDK might not be available or ideal. When using the REST API, its essential to be familiar with the HTTP methods (GET, POST, etc.) and to have a tool or library to make these requests. For the sake of demonstration, Ill be using curl command-line tool to make the API requests: ### Authentication of REST API endpoints Almost all the REST API endpoints are protected with HTTP Basic Authentication. HTTP Basic Authentication requires you to send an Authorization header of your Project ID and Authentication in Base64 format. Example: bash curl -L -X GET https://<$EXAMPLE>.signalwire.com/api/laml/2010-04-01/Accounts/<$PROJECT_ID> \ -H Authorization: Basic <$Base64_Token> This should be supported in almost all HTTP clients. ### Setting up the conference with callbacks using the REST API bash # Making a call and connecting it to a conference curl -L -X POST https://<$EXAMPLE>.signalwire.com/api/laml/2010-04-01/Accounts/<$PROJECT_ID>/Calls \ -H Content-Type: application/x-www-form-urlencoded -H Accept: application/json -H Authorization: Basic <$Base64Token> --data-urlencode To=