> ## Documentation Index
> Fetch the complete documentation index at: https://docs.play.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Create an AI Podcast

> Learn how to create engaging AI-powered podcasts using PlayAI

This guide provides a step-by-step approach to using the PlayAI's Dialog 1.0 model to create a multi-turn scripted conversation between two distinct speakers.

## Overview&#x20;

* This is an async API endpoint.&#x20;

* You will make a request to trigger podcast generation.

* You will then request another endpoint to see if the podcast is ready.

## Prerequisites

* Access your [credentials](https://play.ai/api/keys) (secret key and user ID).
* Development environment for your chosen programming language.

## Steps

<Steps>
  <Step title="Set up environment variables">
    Choose your operating system and set up the environment variables:

    <CodeGroup>
      ```bash macOS (zsh) theme={null}
      echo 'export PLAYAI_API_KEY="your_api_key_here"' >> ~/.zshrc
      echo 'export PLAYAI_USER_ID="your_user_id_here"' >> ~/.zshrc
      source ~/.zshrc
      ```

      ```bash bash theme={null}
      echo 'export PLAYAI_API_KEY="your_api_key_here"' >> ~/.bashrc
      echo 'export PLAYAI_USER_ID="your_user_id_here"' >> ~/.bashrc
      source ~/.bashrc
      ```

      ```cmd Windows theme={null}
      setx PLAYAI_API_KEY "your_api_key_here"
      setx PLAYAI_USER_ID "your_user_id_here"
      ```
    </CodeGroup>
  </Step>

  <Step title="Create a new script">
    Create a new file and add the following code:

    <CodeGroup>
      ```python Python theme={null}
      import requests
      import os
      import time

      # Set up headers with your API secrety key and user ID
      user_id = os.getenv("PLAYAI_USER_ID")
      secret_key = os.getenv("PLAYAI_API_KEY")

      headers = {
          'X-USER-ID': user_id,
          'Authorization': secret_key,
          'Content-Type': 'application/json',
      }
      ```

      ```javascript JavaScript theme={null}
      const axios = require('axios');
      require('dotenv').config();

      // Set up headers with your API secret key and user ID
      const headers = {
          'X-USER-ID': process.env.PLAYAI_USER_ID,
          'Authorization': process.env.PLAYAI_API_KEY,
          'Content-Type': 'application/json',
      };
      ```

      ```go Go theme={null}
      package main

      import (
          "bytes"
          "encoding/json"
          "fmt"
          "io"
          "net/http"
          "os"
          "time"
      )
      ```

      ```dart Dart theme={null}
      import 'dart:convert';
      import 'package:http/http.dart' as http;
      import 'package:dotenv/dotenv.dart';
      ```

      ```swift Swift theme={null}
      import Foundation
      ```

      ```rust Rust theme={null}
      use reqwest::Client;
      use serde::{Deserialize, Serialize};
      use std::env;
      use tokio;
      ```
    </CodeGroup>
  </Step>

  <Step title="Configure the model and voices">
    Define the model and select voices for your hosts:

    <CodeGroup>
      ```python Python theme={null}
      # define the model
      model = 'PlayDialog'

      # define voices for the 2 hosts
      # find all voices here https://docs.play.ai/tts-api-reference/voices
      voice_1 = 's3://voice-cloning-zero-shot/baf1ef41-36b6-428c-9bdf-50ba54682bd8/original/manifest.json'
      voice_2 = 's3://voice-cloning-zero-shot/e040bd1b-f190-4bdb-83f0-75ef85b18f84/original/manifest.json'
      ```

      ```javascript JavaScript theme={null}
      // Define the model
      const model = 'PlayDialog';

      // Define voices for the 2 hosts
      const voice1 = 's3://voice-cloning-zero-shot/baf1ef41-36b6-428c-9bdf-50ba54682bd8/original/manifest.json';
      const voice2 = 's3://voice-cloning-zero-shot/e040bd1b-f190-4bdb-83f0-75ef85b18f84/original/manifest.json';
      ```

      ```go Go theme={null}
      // Define the model and voices
      model := "PlayDialog"
      voice1 := "s3://voice-cloning-zero-shot/baf1ef41-36b6-428c-9bdf-50ba54682bd8/original/manifest.json"
      voice2 := "s3://voice-cloning-zero-shot/e040bd1b-f190-4bdb-83f0-75ef85b18f84/original/manifest.json"
      ```

      ```dart Dart theme={null}
      // Define the model and voices
      const model = 'PlayDialog';
      const voice1 = 's3://voice-cloning-zero-shot/baf1ef41-36b6-428c-9bdf-50ba54682bd8/original/manifest.json';
      const voice2 = 's3://voice-cloning-zero-shot/e040bd1b-f190-4bdb-83f0-75ef85b18f84/original/manifest.json';
      ```

      ```swift Swift theme={null}
      // Define the model and voices
      let model = "PlayDialog"
      let voice1 = "s3://voice-cloning-zero-shot/baf1ef41-36b6-428c-9bdf-50ba54682bd8/original/manifest.json"
      let voice2 = "s3://voice-cloning-zero-shot/e040bd1b-f190-4bdb-83f0-75ef85b18f84/original/manifest.json"
      ```

      ```rust Rust theme={null}
      // Define the model and voices
      let model = "PlayDialog";
      let voice1 = "s3://voice-cloning-zero-shot/baf1ef41-36b6-428c-9bdf-50ba54682bd8/original/manifest.json";
      let voice2 = "s3://voice-cloning-zero-shot/e040bd1b-f190-4bdb-83f0-75ef85b18f84/original/manifest.json";
      ```
    </CodeGroup>
  </Step>

  <Step title="Add your podcast transcript">
    Add your scripted conversation in the correct format:

    <CodeGroup>
      ```python Python theme={null}
      # podcast transcript should be in the format of Host 1: ... Host 2:
      transcript = """
      Host 1: Welcome to The Tech Tomorrow Podcast! Today we're diving into the fascinating world of voice AI and what the future holds.
      Host 2: And what a topic this is. The technology has come so far from those early days of basic voice commands.
      Host 1: Remember when we thought it was revolutionary just to ask our phones to set a timer?
      Host 2: Now we're having full conversations with AI that can understand context, emotion, and even cultural nuances. It's incredible.
      Host 1: Though it does raise some interesting questions about privacy and ethics. Where do we draw the line?
      Host 2: Exactly. The potential benefits for accessibility and education are huge, but we need to be thoughtful about implementation.
      Host 1: Well, we'll be exploring all of these aspects today. Stay with us as we break down the future of voice AI.
      """
      ```

      ```javascript JavaScript theme={null}
      // Podcast transcript
      const transcript = `
      Host 1: Welcome to The Tech Tomorrow Podcast! Today we're diving into the fascinating world of voice AI and what the future holds.
      Host 2: And what a topic this is. The technology has come so far from those early days of basic voice commands.
      Host 1: Remember when we thought it was revolutionary just to ask our phones to set a timer?
      Host 2: Now we're having full conversations with AI that can understand context, emotion, and even cultural nuances. It's incredible.
      Host 1: Though it does raise some interesting questions about privacy and ethics. Where do we draw the line?
      Host 2: Exactly. The potential benefits for accessibility and education are huge, but we need to be thoughtful about implementation.
      Host 1: Well, we'll be exploring all of these aspects today. Stay with us as we break down the future of voice AI.
      `;
      ```

      ```go Go theme={null}
      // Podcast transcript
      transcript := `
      Host 1: Welcome to The Tech Tomorrow Podcast! Today we're diving into the fascinating world of voice AI and what the future holds.
      Host 2: And what a topic this is. The technology has come so far from those early days of basic voice commands.
      Host 1: Remember when we thought it was revolutionary just to ask our phones to set a timer?
      Host 2: Now we're having full conversations with AI that can understand context, emotion, and even cultural nuances. It's incredible.
      Host 1: Though it does raise some interesting questions about privacy and ethics. Where do we draw the line?
      Host 2: Exactly. The potential benefits for accessibility and education are huge, but we need to be thoughtful about implementation.
      Host 1: Well, we'll be exploring all of these aspects today. Stay with us as we break down the future of voice AI.
      `
      ```

      ```dart Dart theme={null}
      // Podcast transcript
      const transcript = '''
      Host 1: Welcome to The Tech Tomorrow Podcast! Today we're diving into the fascinating world of voice AI and what the future holds.
      Host 2: And what a topic this is. The technology has come so far from those early days of basic voice commands.
      Host 1: Remember when we thought it was revolutionary just to ask our phones to set a timer?
      Host 2: Now we're having full conversations with AI that can understand context, emotion, and even cultural nuances. It's incredible.
      Host 1: Though it does raise some interesting questions about privacy and ethics. Where do we draw the line?
      Host 2: Exactly. The potential benefits for accessibility and education are huge, but we need to be thoughtful about implementation.
      Host 1: Well, we'll be exploring all of these aspects today. Stay with us as we break down the future of voice AI.
      ''';
      ```

      ```swift Swift theme={null}
      // Podcast transcript
      let transcript = """
      Host 1: Welcome to The Tech Tomorrow Podcast! Today we're diving into the fascinating world of voice AI and what the future holds.
      Host 2: And what a topic this is. The technology has come so far from those early days of basic voice commands.
      Host 1: Remember when we thought it was revolutionary just to ask our phones to set a timer?
      Host 2: Now we're having full conversations with AI that can understand context, emotion, and even cultural nuances. It's incredible.
      Host 1: Though it does raise some interesting questions about privacy and ethics. Where do we draw the line?
      Host 2: Exactly. The potential benefits for accessibility and education are huge, but we need to be thoughtful about implementation.
      Host 1: Well, we'll be exploring all of these aspects today. Stay with us as we break down the future of voice AI.
      """
      ```

      ```rust Rust theme={null}
      // Podcast transcript
      let transcript = r#"
      Host 1: Welcome to The Tech Tomorrow Podcast! Today we're diving into the fascinating world of voice AI and what the future holds.
      Host 2: And what a topic this is. The technology has come so far from those early days of basic voice commands.
      Host 1: Remember when we thought it was revolutionary just to ask our phones to set a timer?
      Host 2: Now we're having full conversations with AI that can understand context, emotion, and even cultural nuances. It's incredible.
      Host 1: Though it does raise some interesting questions about privacy and ethics. Where do we draw the line?
      Host 2: Exactly. The potential benefits for accessibility and education are huge, but we need to be thoughtful about implementation.
      Host 1: Well, we'll be exploring all of these aspects today. Stay with us as we break down the future of voice AI.
      "#;
      ```
    </CodeGroup>
  </Step>

  <Step title="Configure the API payload">
    Set up the payload with your configuration:

    <CodeGroup>
      ```python Python theme={null}
      payload = {
          'model': model,
          'text': transcript,
          'voice': voice_1,
          'voice2': voice_2,
          'turnPrefix': 'Host 1:',
          'turnPrefix2': 'Host 2:',
          'outputFormat': 'mp3',
      }
      ```

      ```javascript JavaScript theme={null}
      const payload = {
          model,
          text: transcript,
          voice: voice1,
          voice2,
          turnPrefix: 'Host 1:',
          turnPrefix2: 'Host 2:',
          outputFormat: 'mp3',
      };
      ```

      ```go Go theme={null}
      payload := Payload{
          Model:        model,
          Text:         transcript,
          Voice:        voice1,
          Voice2:       voice2,
          TurnPrefix:   "Host 1:",
          TurnPrefix2:  "Host 2:",
          OutputFormat: "mp3",
      }
      ```

      ```dart Dart theme={null}
      final payload = {
          'model': model,
          'text': transcript,
          'voice': voice1,
          'voice2': voice2,
          'turnPrefix': 'Host 1:',
          'turnPrefix2': 'Host 2:',
          'outputFormat': 'mp3',
      };
      ```

      ```swift Swift theme={null}
      let payload = Payload(
          model: model,
          text: transcript,
          voice: voice1,
          voice2: voice2,
          turnPrefix: "Host 1:",
          turnPrefix2: "Host 2:",
          outputFormat: "mp3"
      )
      ```

      ```rust Rust theme={null}
      let payload = serde_json::json!({
          "model": model,
          "text": transcript,
          "voice": voice1,
          "voice2": voice2,
          "turnPrefix": "Host 1:",
          "turnPrefix2": "Host 2:",
          "outputFormat": "mp3"
      });
      ```
    </CodeGroup>
  </Step>

  <Step title="Send the request and monitor progress">
    Add the code to send the request and check the status:

    <CodeGroup>
      ```python Python [expandable] theme={null}
      # Send the POST request to trigger podcast generation
      response = requests.post('https://api.play.ai/api/v1/tts/', headers=headers, json=payload)

      # get the job id to check the status
      job_id = response.json().get('id')

      # use the job id to check completion status
      url = f'https://api.play.ai/api/v1/tts/{job_id}'
      delay_seconds = 2

      # keep checking until status is COMPLETED.
      # longer transcripts take more time to complete.
      while True:
          response = requests.get(url, headers=headers)

          if response.ok:
              status = response.json().get('output', {}).get('status')
              print(status)
              if status == 'COMPLETED':
                  # once completed audio url will be avaialable
                  podcast_audio = response.json().get('output', {}).get('url')
                  break

          time.sleep(delay_seconds)

      print(podcast_audio)
      ```

      ```javascript JavaScript [expandable] theme={null}
      async function generatePodcast() {
          try {
              // Send the POST request to trigger podcast generation
              const response = await axios.post('https://api.play.ai/api/v1/tts/', payload, { headers });
              const jobId = response.data.id;

              // Check status until completed
              while (true) {
                  const statusResponse = await axios.get(`https://api.play.ai/api/v1/tts/${jobId}`, { headers });

                  if (statusResponse.data.output?.status === 'COMPLETED') {
                      const podcastAudio = statusResponse.data.output.url;
                      console.log(podcastAudio);
                      break;
                  }

                  console.log(statusResponse.data.output?.status);
                  await new Promise(resolve => setTimeout(resolve, 2000));
              }
          } catch (error) {
              console.error('Error:', error.message);
          }
      }

      generatePodcast();
      ```

      ```go Go [expandable] theme={null}
      // Send request
      client := &http.Client{}
      resp, err := client.Do(req)
      if err != nil {
          fmt.Println("Error sending request:", err)
          return
      }
      defer resp.Body.Close()

      // Read response
      body, err := io.ReadAll(resp.Body)
      if err != nil {
          fmt.Println("Error reading response:", err)
          return
      }

      var response Response
      if err := json.Unmarshal(body, &response); err != nil {
          fmt.Println("Error unmarshaling response:", err)
          return
      }

      jobID := response.ID

      // Check status until completed
      for {
          req, err := http.NewRequest("GET", fmt.Sprintf("https://api.play.ai/api/v1/tts/%s", jobID), nil)
          if err != nil {
              fmt.Println("Error creating status request:", err)
              return
          }

          for key, value := range headers {
              req.Header.Add(key, value)
          }

          resp, err := client.Do(req)
          if err != nil {
              fmt.Println("Error checking status:", err)
              return
          }

          body, err := io.ReadAll(resp.Body)
          resp.Body.Close()

          if err != nil {
              fmt.Println("Error reading status response:", err)
              return
          }

          var statusResponse Response
          if err := json.Unmarshal(body, &statusResponse); err != nil {
              fmt.Println("Error unmarshaling status response:", err)
              return
          }

          fmt.Println(statusResponse.Output.Status)

          if statusResponse.Output.Status == "COMPLETED" {
              fmt.Println(statusResponse.Output.URL)
              break
          }

          time.Sleep(2 * time.Second)
      }
      ```

      ```dart Dart [expandable] theme={null}
      try {
          // Send the POST request to trigger podcast generation
          final response = await http.post(
              Uri.parse('https://api.play.ai/api/v1/tts/'),
              headers: headers,
              body: jsonEncode(payload),
          );

          if (response.statusCode == 200) {
              final jobId = jsonDecode(response.body)['id'];

              // Check status until completed
              while (true) {
                  final statusResponse = await http.get(
                      Uri.parse('https://api.play.ai/api/v1/tts/$jobId'),
                      headers: headers,
                  );

                  if (statusResponse.statusCode == 200) {
                      final statusData = jsonDecode(statusResponse.body);
                      final status = statusData['output']['status'];
                      print(status);

                      if (status == 'COMPLETED') {
                          final podcastAudio = statusData['output']['url'];
                          print(podcastAudio);
                          break;
                      }
                  }

                  await Future.delayed(const Duration(seconds: 2));
              }
          } else {
              print('Error: ${response.statusCode}');
              print(response.body);
          }
      } catch (e) {
          print('Error: $e');
      }
      ```

      ```swift Swift [expandable] theme={null}
      // Send request
      let (data, _) = try await URLSession.shared.data(for: request)
      let response = try JSONDecoder().decode(Response.self, from: data)
      let jobId = response.id

      // Check status until completed
      while true {
          var statusRequest = URLRequest(url: URL(string: "https://api.play.ai/api/v1/tts/\(jobId)")!)
          statusRequest.allHTTPHeaderFields = headers

          let (statusData, _) = try await URLSession.shared.data(for: statusRequest)
          let statusResponse = try JSONDecoder().decode(Response.self, from: statusData)

          print(statusResponse.output.status)

          if statusResponse.output.status == "COMPLETED" {
              if let podcastAudio = statusResponse.output.url {
                  print(podcastAudio)
              }
              break
          }

          try await Task.sleep(nanoseconds: 2_000_000_000) // 2 seconds
      }
      ```

      ```rust Rust [expandable] theme={null}
      // Create HTTP client
      let client = Client::new();

      // Send request
      let response = client
          .post("https://api.play.ai/api/v1/tts/")
          .headers(headers.clone())
          .json(&payload)
          .send()
          .await?;

      let response_data: Response = response.json().await?;
      let job_id = response_data.id;

      // Check status until completed
      loop {
          let status_response = client
              .get(&format!("https://api.play.ai/api/v1/tts/{}", job_id))
              .headers(headers.clone())
              .send()
              .await?;

          let status_data: Response = status_response.json().await?;
          println!("{}", status_data.output.status);

          if status_data.output.status == "COMPLETED" {
              if let Some(url) = status_data.output.url {
                  println!("{}", url);
              }
              break;
          }

          tokio::time::sleep(tokio::time::Duration::from_secs(2)).await;
      }

      Ok(())
      ```
    </CodeGroup>
  </Step>
</Steps>

## Complete Code

<CodeGroup>
  ```python Python [expandable] theme={null}
  import requests
  import os
  import time

  # Set up headers with your API secrety key and user ID
  user_id = os.getenv("PLAYAI_USER_ID")
  secret_key = os.getenv("PLAYAI_API_KEY")

  headers = {
      'X-USER-ID': user_id,
      'Authorization': secret_key,
      'Content-Type': 'application/json',
  }

  # define the model
  model = 'PlayDialog'

  # define voices for the 2 hosts
  # find all voices here https://docs.play.ai/tts-api-reference/voices
  voice_1 = 's3://voice-cloning-zero-shot/baf1ef41-36b6-428c-9bdf-50ba54682bd8/original/manifest.json'
  voice_2 = 's3://voice-cloning-zero-shot/e040bd1b-f190-4bdb-83f0-75ef85b18f84/original/manifest.json'

  # podcast transcript should be in the format of Host 1: ... Host 2:
  transcript = """
  Host 1: Welcome to The Tech Tomorrow Podcast! Today we're diving into the fascinating world of voice AI and what the future holds.
  Host 2: And what a topic this is. The technology has come so far from those early days of basic voice commands.
  Host 1: Remember when we thought it was revolutionary just to ask our phones to set a timer?
  Host 2: Now we're having full conversations with AI that can understand context, emotion, and even cultural nuances. It's incredible.
  Host 1: Though it does raise some interesting questions about privacy and ethics. Where do we draw the line?
  Host 2: Exactly. The potential benefits for accessibility and education are huge, but we need to be thoughtful about implementation.
  Host 1: Well, we'll be exploring all of these aspects today. Stay with us as we break down the future of voice AI.
  """

  payload = {
      'model': model,
      'text': transcript,
      'voice': voice_1,
      'voice2': voice_2,
      'turnPrefix': 'Host 1:',
      'turnPrefix2': 'Host 2:',
      'outputFormat': 'mp3',
  }

  # Send the POST request to trigger podcast generation
  response = requests.post('https://api.play.ai/api/v1/tts/', headers=headers, json=payload)

  # get the job id to check the status
  job_id = response.json().get('id')

  # use the job id to check completion status
  url = f'https://api.play.ai/api/v1/tts/{job_id}'
  delay_seconds = 2

  # keep checking until status is COMPLETED.
  # longer transcripts take more time to complete.
  while True:
      response = requests.get(url, headers=headers)

      if response.ok:
          status = response.json().get('output', {}).get('status')
          print(status)
          if status == 'COMPLETED':
              # once completed audio url will be avaialable
              podcast_audio = response.json().get('output', {}).get('url')
              break

      time.sleep(delay_seconds)

  print(podcast_audio)
  ```

  ```javascript JavaScript [expandable] theme={null}
  const axios = require('axios');
  require('dotenv').config();

  // Set up headers with your API secret key and user ID
  const headers = {
    'X-USER-ID': process.env.PLAYAI_USER_ID,
    Authorization: process.env.PLAYAI_API_KEY,
    'Content-Type': 'application/json',
  };

  // Define the model
  const model = 'PlayDialog';

  // Define voices for the 2 hosts
  const voice1 = 's3://voice-cloning-zero-shot/baf1ef41-36b6-428c-9bdf-50ba54682bd8/original/manifest.json';
  const voice2 = 's3://voice-cloning-zero-shot/e040bd1b-f190-4bdb-83f0-75ef85b18f84/original/manifest.json';

  // Podcast transcript
  const transcript = `
  Host 1: Welcome to The Tech Tomorrow Podcast! Today we're diving into the fascinating world of voice AI and what the future holds.
  Host 2: And what a topic this is. The technology has come so far from those early days of basic voice commands.
  Host 1: Remember when we thought it was revolutionary just to ask our phones to set a timer?
  Host 2: Now we're having full conversations with AI that can understand context, emotion, and even cultural nuances. It's incredible.
  Host 1: Though it does raise some interesting questions about privacy and ethics. Where do we draw the line?
  Host 2: Exactly. The potential benefits for accessibility and education are huge, but we need to be thoughtful about implementation.
  Host 1: Well, we'll be exploring all of these aspects today. Stay with us as we break down the future of voice AI.
  `;

  const payload = {
    model,
    text: transcript,
    voice: voice1,
    voice2,
    turnPrefix: 'Host 1:',
    turnPrefix2: 'Host 2:',
    outputFormat: 'mp3',
  };

  async function generatePodcast() {
    try {
      // Send the POST request to trigger podcast generation
      const response = await axios.post('https://api.play.ai/api/v1/tts/', payload, { headers });
      const jobId = response.data.id;

      // Check status until completed
      while (true) {
        const statusResponse = await axios.get(`https://api.play.ai/api/v1/tts/${jobId}`, { headers });

        if (statusResponse.data.output?.status === 'COMPLETED') {
          const podcastAudio = statusResponse.data.output.url;
          console.log(podcastAudio);
          break;
        }

        console.log(statusResponse.data.output?.status);
        await new Promise((resolve) => setTimeout(resolve, 2000));
      }
    } catch (error) {
      console.error('Error:', error.message);
    }
  }

  generatePodcast();
  ```

  ```go Go [expandable] theme={null}
  package main

  import (
      "bytes"
      "encoding/json"
      "fmt"
      "io"
      "net/http"
      "os"
      "time"
  )

  type Payload struct {
      Model        string `json:"model"`
      Text         string `json:"text"`
      Voice        string `json:"voice"`
      Voice2       string `json:"voice2"`
      TurnPrefix   string `json:"turnPrefix"`
      TurnPrefix2  string `json:"turnPrefix2"`
      OutputFormat string `json:"outputFormat"`
  }

  type Response struct {
      ID     string `json:"id"`
      Output struct {
          Status string `json:"status"`
          URL    string `json:"url"`
      } `json:"output"`
  }

  func main() {
      // Set up headers
      headers := map[string]string{
          "X-USER-ID":     os.Getenv("PLAYAI_USER_ID"),
          "Authorization": os.Getenv("PLAYAI_API_KEY"),
          "Content-Type":  "application/json",
      }

      // Define the model and voices
      model := "PlayDialog"
      voice1 := "s3://voice-cloning-zero-shot/baf1ef41-36b6-428c-9bdf-50ba54682bd8/original/manifest.json"
      voice2 := "s3://voice-cloning-zero-shot/e040bd1b-f190-4bdb-83f0-75ef85b18f84/original/manifest.json"

      // Podcast transcript
      transcript := `
      Host 1: Welcome to The Tech Tomorrow Podcast! Today we're diving into the fascinating world of voice AI and what the future holds.
      Host 2: And what a topic this is. The technology has come so far from those early days of basic voice commands.
      Host 1: Remember when we thought it was revolutionary just to ask our phones to set a timer?
      Host 2: Now we're having full conversations with AI that can understand context, emotion, and even cultural nuances. It's incredible.
      Host 1: Though it does raise some interesting questions about privacy and ethics. Where do we draw the line?
      Host 2: Exactly. The potential benefits for accessibility and education are huge, but we need to be thoughtful about implementation.
      Host 1: Well, we'll be exploring all of these aspects today. Stay with us as we break down the future of voice AI.
      `

      payload := Payload{
          Model:        model,
          Text:         transcript,
          Voice:        voice1,
          Voice2:       voice2,
          TurnPrefix:   "Host 1:",
          TurnPrefix2:  "Host 2:",
          OutputFormat: "mp3",
      }

      jsonData, err := json.Marshal(payload)
      if err != nil {
          fmt.Println("Error marshaling payload:", err)
          return
      }

      // Create request
      req, err := http.NewRequest("POST", "https://api.play.ai/api/v1/tts/", bytes.NewBuffer(jsonData))
      if err != nil {
          fmt.Println("Error creating request:", err)
          return
      }

      // Add headers
      for key, value := range headers {
          req.Header.Add(key, value)
      }

      // Send request
      client := &http.Client{}
      resp, err := client.Do(req)
      if err != nil {
          fmt.Println("Error sending request:", err)
          return
      }
      defer resp.Body.Close()

      // Read response
      body, err := io.ReadAll(resp.Body)
      if err != nil {
          fmt.Println("Error reading response:", err)
          return
      }

      var response Response
      if err := json.Unmarshal(body, &response); err != nil {
          fmt.Println("Error unmarshaling response:", err)
          return
      }

      jobID := response.ID

      // Check status until completed
      for {
          req, err := http.NewRequest("GET", fmt.Sprintf("https://api.play.ai/api/v1/tts/%s", jobID), nil)
          if err != nil {
              fmt.Println("Error creating status request:", err)
              return
          }

          for key, value := range headers {
              req.Header.Add(key, value)
          }

          resp, err := client.Do(req)
          if err != nil {
              fmt.Println("Error checking status:", err)
              return
          }

          body, err := io.ReadAll(resp.Body)
          resp.Body.Close()

          if err != nil {
              fmt.Println("Error reading status response:", err)
              return
          }

          var statusResponse Response
          if err := json.Unmarshal(body, &statusResponse); err != nil {
              fmt.Println("Error unmarshaling status response:", err)
              return
          }

          fmt.Println(statusResponse.Output.Status)

          if statusResponse.Output.Status == "COMPLETED" {
              fmt.Println(statusResponse.Output.URL)
              break
          }

          time.Sleep(2 * time.Second)
      }
  }
  ```

  ```dart Dart [expandable] theme={null}
  import 'dart:convert';
  import 'package:http/http.dart' as http;
  import 'package:dotenv/dotenv.dart';

  void main() async {
      // Load environment variables
      var env = DotEnv(includePlatformEnvironment: true)..load();

      // Set up headers
      final headers = {
          'X-USER-ID': env['PLAYAI_USER_ID'] ?? '',
          'Authorization': env['PLAYAI_API_KEY'] ?? '',
          'Content-Type': 'application/json',
      };

      // Define the model and voices
      const model = 'PlayDialog';
      const voice1 = 's3://voice-cloning-zero-shot/baf1ef41-36b6-428c-9bdf-50ba54682bd8/original/manifest.json';
      const voice2 = 's3://voice-cloning-zero-shot/e040bd1b-f190-4bdb-83f0-75ef85b18f84/original/manifest.json';

      // Podcast transcript
      const transcript = '''
      Host 1: Welcome to The Tech Tomorrow Podcast! Today we're diving into the fascinating world of voice AI and what the future holds.
      Host 2: And what a topic this is. The technology has come so far from those early days of basic voice commands.
      Host 1: Remember when we thought it was revolutionary just to ask our phones to set a timer?
      Host 2: Now we're having full conversations with AI that can understand context, emotion, and even cultural nuances. It's incredible.
      Host 1: Though it does raise some interesting questions about privacy and ethics. Where do we draw the line?
      Host 2: Exactly. The potential benefits for accessibility and education are huge, but we need to be thoughtful about implementation.
      Host 1: Well, we'll be exploring all of these aspects today. Stay with us as we break down the future of voice AI.
      ''';

      final payload = {
          'model': model,
          'text': transcript,
          'voice': voice1,
          'voice2': voice2,
          'turnPrefix': 'Host 1:',
          'turnPrefix2': 'Host 2:',
          'outputFormat': 'mp3',
      };

      try {
          // Send the POST request to trigger podcast generation
          final response = await http.post(
              Uri.parse('https://api.play.ai/api/v1/tts/'),
              headers: headers,
              body: jsonEncode(payload),
          );

          if (response.statusCode == 200) {
              final jobId = jsonDecode(response.body)['id'];

              // Check status until completed
              while (true) {
                  final statusResponse = await http.get(
                      Uri.parse('https://api.play.ai/api/v1/tts/$jobId'),
                      headers: headers,
                  );

                  if (statusResponse.statusCode == 200) {
                      final statusData = jsonDecode(statusResponse.body);
                      final status = statusData['output']['status'];
                      print(status);

                      if (status == 'COMPLETED') {
                          final podcastAudio = statusData['output']['url'];
                          print(podcastAudio);
                          break;
                      }
                  }

                  await Future.delayed(const Duration(seconds: 2));
              }
          } else {
              print('Error: ${response.statusCode}');
              print(response.body);
          }
      } catch (e) {
          print('Error: $e');
      }
  }
  ```

  ```swift Swift [expandable] theme={null}
  import Foundation

  struct Payload: Codable {
      let model: String
      let text: String
      let voice: String
      let voice2: String
      let turnPrefix: String
      let turnPrefix2: String
      let outputFormat: String
  }

  struct Response: Codable {
      let id: String
      let output: Output
  }

  struct Output: Codable {
      let status: String
      let url: String?
  }

  func generatePodcast() async throws {
      // Set up headers
      let headers = [
          "X-USER-ID": ProcessInfo.processInfo.environment["PLAYAI_USER_ID"] ?? "",
          "Authorization": ProcessInfo.processInfo.environment["PLAYAI_API_KEY"] ?? "",
          "Content-Type": "application/json"
      ]

      // Define the model and voices
      let model = "PlayDialog"
      let voice1 = "s3://voice-cloning-zero-shot/baf1ef41-36b6-428c-9bdf-50ba54682bd8/original/manifest.json"
      let voice2 = "s3://voice-cloning-zero-shot/e040bd1b-f190-4bdb-83f0-75ef85b18f84/original/manifest.json"

      // Podcast transcript
      let transcript = """
      Host 1: Welcome to The Tech Tomorrow Podcast! Today we're diving into the fascinating world of voice AI and what the future holds.
      Host 2: And what a topic this is. The technology has come so far from those early days of basic voice commands.
      Host 1: Remember when we thought it was revolutionary just to ask our phones to set a timer?
      Host 2: Now we're having full conversations with AI that can understand context, emotion, and even cultural nuances. It's incredible.
      Host 1: Though it does raise some interesting questions about privacy and ethics. Where do we draw the line?
      Host 2: Exactly. The potential benefits for accessibility and education are huge, but we need to be thoughtful about implementation.
      Host 1: Well, we'll be exploring all of these aspects today. Stay with us as we break down the future of voice AI.
      """

      let payload = Payload(
          model: model,
          text: transcript,
          voice: voice1,
          voice2: voice2,
          turnPrefix: "Host 1:",
          turnPrefix2: "Host 2:",
          outputFormat: "mp3"
      )

      // Create URL request
      var request = URLRequest(url: URL(string: "https://api.play.ai/api/v1/tts/")!)
      request.httpMethod = "POST"
      request.allHTTPHeaderFields = headers
      request.httpBody = try JSONEncoder().encode(payload)

      // Send request
      let (data, _) = try await URLSession.shared.data(for: request)
      let response = try JSONDecoder().decode(Response.self, from: data)
      let jobId = response.id

      // Check status until completed
      while true {
          var statusRequest = URLRequest(url: URL(string: "https://api.play.ai/api/v1/tts/\(jobId)")!)
          statusRequest.allHTTPHeaderFields = headers

          let (statusData, _) = try await URLSession.shared.data(for: statusRequest)
          let statusResponse = try JSONDecoder().decode(Response.self, from: statusData)

          print(statusResponse.output.status)

          if statusResponse.output.status == "COMPLETED" {
              if let podcastAudio = statusResponse.output.url {
                  print(podcastAudio)
              }
              break
          }

          try await Task.sleep(nanoseconds: 2_000_000_000) // 2 seconds
      }
  }

  // Run the async function
  Task {
      do {
          try await generatePodcast()
      } catch {
          print("Error: \(error)")
      }
  }
  ```

  ```rust Rust [expandable] theme={null}
  use reqwest::Client;
  use serde::{Deserialize, Serialize};
  use std::env;
  use tokio;

  #[derive(Serialize)]
  struct Payload {
      model: String,
      text: String,
      voice: String,
      voice2: String,
      turn_prefix: String,
      turn_prefix2: String,
      output_format: String,
  }

  #[derive(Deserialize)]
  struct Response {
      id: String,
      output: Output,
  }

  #[derive(Deserialize)]
  struct Output {
      status: String,
      url: Option<String>,
  }

  #[tokio::main]
  async fn main() -> Result<(), Box<dyn std::error::Error>> {
      // Set up headers
      let headers = {
          let mut headers = reqwest::header::HeaderMap::new();
          headers.insert(
              "X-USER-ID",
              env::var("PLAYAI_USER_ID")?.parse()?,
          );
          headers.insert(
              "Authorization",
              env::var("PLAYAI_API_KEY")?.parse()?,
          );
          headers.insert(
              "Content-Type",
              "application/json".parse()?,
          );
          headers
      };

      // Define the model and voices
      let model = "PlayDialog";
      let voice1 = "s3://voice-cloning-zero-shot/baf1ef41-36b6-428c-9bdf-50ba54682bd8/original/manifest.json";
      let voice2 = "s3://voice-cloning-zero-shot/e040bd1b-f190-4bdb-83f0-75ef85b18f84/original/manifest.json";

      // Podcast transcript
      let transcript = r#"
      Host 1: Welcome to The Tech Tomorrow Podcast! Today we're diving into the fascinating world of voice AI and what the future holds.
      Host 2: And what a topic this is. The technology has come so far from those early days of basic voice commands.
      Host 1: Remember when we thought it was revolutionary just to ask our phones to set a timer?
      Host 2: Now we're having full conversations with AI that can understand context, emotion, and even cultural nuances. It's incredible.
      Host 1: Though it does raise some interesting questions about privacy and ethics. Where do we draw the line?
      Host 2: Exactly. The potential benefits for accessibility and education are huge, but we need to be thoughtful about implementation.
      Host 1: Well, we'll be exploring all of these aspects today. Stay with us as we break down the future of voice AI.
      "#;

      let payload = Payload {
          model: model.to_string(),
          text: transcript.to_string(),
          voice: voice1.to_string(),
          voice2: voice2.to_string(),
          turn_prefix: "Host 1:".to_string(),
          turn_prefix2: "Host 2:".to_string(),
          output_format: "mp3".to_string(),
      };

      // Create HTTP client
      let client = Client::new();

      // Send request
      let response = client
          .post("https://api.play.ai/api/v1/tts/")
          .headers(headers.clone())
          .json(&payload)
          .send()
          .await?;

      let response_data: Response = response.json().await?;
      let job_id = response_data.id;

      // Check status until completed
      loop {
          let status_response = client
              .get(&format!("https://api.play.ai/api/v1/tts/{}", job_id))
              .headers(headers.clone())
              .send()
              .await?;

          let status_data: Response = status_response.json().await?;
          println!("{}", status_data.output.status);

          if status_data.output.status == "COMPLETED" {
              if let Some(url) = status_data.output.url {
                  println!("{}", url);
              }
              break;
          }

          tokio::time::sleep(tokio::time::Duration::from_secs(2)).await;
      }

      Ok(())
  }
  ```
</CodeGroup>

## Key API Parameters

The following API payload define the conversation, speaker details, and audio generation options:

* **`model`**: Specifies the PlayAI's Dialog 1.0 model to be used. Here, `PlayDialog` supports multi-turn conversation generation.

* **`text`**: Contains the scripted conversation, with each turn prefixed by the speaker's name (e.g., `"Country Mouse"` & `"Town Mouse"`).

* **`voice`**: URL path to the voice manifest for the first speaker.

* **`voice_2`**: URL path to the voice manifest for the second speaker.

* **`turn_prefix` / `turn_prefix_2`**: Used to specify each speaker's dialogue turns within the `text` field. For example: `turn_prefix` says `Country Mouse` to indicate the position where Speaker 1's dialogue and `turn_prefix_2` says `Town Mouse` that indicates the position where Speaker 2's dialogue parts are.

* **`output_format`**: Format for the generated audio file, typically `wav` or `mp3`.

If you happen to save the code as `country_mouse.py` then Run the code using `python3 country_mouse.py` pointing your terminal to the directory where the `country_mouse.py` file is stored. This will save the `dialogue.wav` in the same working directory.

# Code Explanation

This script uses the Dialog 1.0 model to generate a multi-turn conversation between two characters. The `AUTHORIZATION token` and `X-USER-ID` are required for authentication, which you'll need to replace with your own credentials.

Each line of dialogue is labeled by character name (e.g., "`Country Mouse`" or "`Town Mouse`") to simulate a natural conversation. The script assigns a unique voice to each character using `voice` and `voice2`. On a successful API call, the generated audio is saved as `dialogue.wav`. Any errors are reported with status details.

**To run the script:**

* Replace placeholders in the headers with your API key and user ID.

* Update the `text` with your scripted conversation

* Update the Speaker Details and their respective voices

* Run the script. If successful, an audio file, `dialogue.wav`, will be saved in the current directory, capturing the dialogue as configured.

* This setup can easily adapt to more complex dialogues or different speakers.

# Troubleshooting

* Authentication Issues: Verify your `API key` and `user ID`. Ensure the `AUTHORIZATION` header includes "Bearer " followed by your token.

* API Endpoint Errors: Confirm you're using the correct PlayAI's Dialog 1.0 API endpoint URL and the `model` name is `PlayDialog`
