Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -69,4 +69,11 @@ docs/_build/
.vscode/

# Pyenv
.python-version
.python-version

# Environment variables
.env

*.wav

demos/audio/uv.lock
10 changes: 10 additions & 0 deletions demos/audio/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# wave_audio_receive.py

six 15 second tests:
```bash
for i in {1..6};do timeout 15s uv run python wav_audio_receive.py; done
```
or
```bash
for i in {1..6};do timeout 15s python3 -m wav_audio_receive; done
```
13 changes: 13 additions & 0 deletions demos/audio/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
[project]
name = "wav-audio-receive"
version = "0.1.0"
description = "Demo that joins a Pipecat Cloud call and records audio to WAV"
requires-python = ">=3.10"
dependencies = [
"daily-python",
"python-dotenv>=1.2.1",
"requests",
]

[project.scripts]
wav-audio-receive = "wav_audio_receive:main"
55 changes: 45 additions & 10 deletions demos/audio/wav_audio_receive.py
Original file line number Diff line number Diff line change
@@ -1,26 +1,30 @@
#
# This demo will join a Daily meeting and record the meeting audio into a
# WAV.
# This demo will start a Pipecat Cloud app, join the call, and record the
# meeting audio into a WAV.
#
# Usage: python3 wav_audio_receive.py -m MEETING_URL -o FILE.wav
#

import argparse
import os
import requests
import threading
import wave

from dotenv import load_dotenv
from daily import *


SAMPLE_RATE = 16000
NUM_CHANNELS = 1

load_dotenv(override=True)


class ReceiveWavApp:
def __init__(self, input_file_name, sample_rate, num_channels):
self.__sample_rate = sample_rate
self.__speaker_device = Daily.create_speaker_device(
"my-speaker", sample_rate=sample_rate, channels=num_channels
"my-speaker", sample_rate=sample_rate, channels=num_channels, non_blocking=False
)
Daily.select_speaker_device("my-speaker")

Expand All @@ -47,8 +51,8 @@ def on_joined(self, data, error):
self.__app_error = error
self.__start_event.set()

def run(self, meeting_url):
self.__client.join(meeting_url, completion=self.on_joined)
def run(self, meeting_url, meeting_token=None):
self.__client.join(meeting_url, meeting_token, completion=self.on_joined)
self.__thread.join()

def leave(self):
Expand All @@ -73,22 +77,53 @@ def receive_audio(self):
self.__wave.close()


def start_pipecat_app(api_key):
response = requests.post(
"https://api.pipecat.daily.co/v1/public/daily-python-virtual-speaker-test/start",
headers={
"Authorization": f"Bearer {api_key}",
"Content-Type": "application/json",
},
json={
"createDailyRoom": True,
"transport": "daily",
"dailyMeetingTokenProperties": {
"is_owner": True
# "enable_auto_recording": True
# "start_cloud_recording": True
},
"dailyRoomProperties": {"enable_recording": "cloud"},
},
)
response.raise_for_status()
data = response.json()
print(f"_____wav_audio_receive.py * data: {data}")
return data["dailyRoom"], data.get("dailyToken")


def main():
parser = argparse.ArgumentParser()
parser.add_argument("-m", "--meeting", required=True, help="Meeting URL")
parser.add_argument("-k", "--api-key", required=False, help="Pipecat API key")
parser.add_argument(
"-c", "--channels", type=int, default=NUM_CHANNELS, help="Number of channels"
)
parser.add_argument("-r", "--rate", type=int, default=SAMPLE_RATE, help="Sample rate")
parser.add_argument("-o", "--output", required=True, help="WAV output file")
# parser.add_argument("-o", "--output", help="WAV output file")
args = parser.parse_args()

Daily.init()

app = ReceiveWavApp(args.output, args.rate, args.channels)
api_key = os.getenv("PIPECAT_API_KEY", args.api_key)
room_url, token = start_pipecat_app(api_key)
print(f"Started Pipecat app: {room_url}")

room_name = room_url.rstrip("/").split("/")[-1]
output = f"{room_name}.wav"
app = ReceiveWavApp(output, args.rate, args.channels)

try:
app.run(args.meeting)
# print(f"_____wav_audio_receive.py * token: {token}")
app.run(room_url, token)
except KeyboardInterrupt:
print("Ctrl-C detected. Exiting!")
finally:
Expand Down