> For a complete index of all SignalWire documentation pages, fetch https://signalwire.com/docs/llms.txt

# play

> Play audio content on a call.

[playaction]: /docs/server-sdks/reference/python/relay/actions

[calling-call-play]: /docs/server-sdks/reference/python/relay/call#events

[call-events]: /docs/server-sdks/reference/python/relay/call#events

[play]: /docs/swml/reference/play

[swml-play-reference]: /docs/swml/reference/play

Play audio content on the call. Supports TTS (text-to-speech), audio file URLs,
silence, and ringtone. Returns a [`PlayAction`][playaction]
that you can use to pause, resume, stop, adjust volume, or wait for completion.

This method emits [`calling.call.play`][calling-call-play] events. See [Call Events][call-events] for payload details.

This method corresponds to the SWML [`play`][play] verb. See the
[SWML play reference][swml-play-reference] for the full specification.

## **Parameters**

List of media items to play. Each item is a dict with a `type` key and
type-specific fields:

* `{"type": "tts", "text": "Hello", "language": "en-US", "gender": "female"}` -- text-to-speech
* `{"type": "audio", "url": "https://example.com/audio.mp3"}` -- audio file URL
* `{"type": "silence", "duration": 2}` -- silence for a duration in seconds
* `{"type": "ringtone", "name": "us"}` -- play a standard ringtone

Volume adjustment in dB, from `-40.0` to `40.0`.

Audio direction. Valid values:

* `"listen"` -- play to the caller only
* `"speak"` -- play to the remote party only
* `"both"` -- play to both sides

Number of times to repeat the media. `0` loops indefinitely.

Custom control ID for this operation. Auto-generated if not provided.

Callback invoked when playback reaches a terminal state. Can be a regular
function or async coroutine.

## **Returns**

[`PlayAction`][playaction] -- An action handle with
`stop()`, `pause()`, `resume()`, `volume()`, and `wait()` methods.

## **Examples**

### Text-to-Speech

```python {13}
from signalwire.relay import RelayClient

client = RelayClient(
    project="your-project-id",
    token="your-api-token",
    host="your-space.signalwire.com",
    contexts=["default"],
)

@client.on_call
async def handle_call(call):
    await call.answer()
    action = await call.play([{"type": "tts", "text": "Welcome to SignalWire!"}])
    await action.wait()

client.run()
```

### Audio File with Loop

```python {14}
from signalwire.relay import RelayClient

client = RelayClient(
    project="your-project-id",
    token="your-api-token",
    host="your-space.signalwire.com",
    contexts=["default"],
)

@client.on_call
async def handle_call(call):
    await call.answer()
    # Play hold music on loop
    action = await call.play(
        [{"type": "audio", "url": "https://example.com/hold-music.mp3"}],
        loop=0,
        direction="listen",
    )
    # Later, stop the music
    await action.stop()

client.run()
```

### Multiple Media Items

```python {13}
from signalwire.relay import RelayClient

client = RelayClient(
    project="your-project-id",
    token="your-api-token",
    host="your-space.signalwire.com",
    contexts=["default"],
)

@client.on_call
async def handle_call(call):
    await call.answer()
    action = await call.play([
        {"type": "tts", "text": "Please hold while we connect you."},
        {"type": "silence", "duration": 1},
        {"type": "audio", "url": "https://example.com/hold-music.mp3"},
    ])
    await action.wait()

client.run()
```