Experience the speed of our new streaming API

We're thrilled to announce that we've release the beta version of our PlayHT2.0-turbo streaming model that promises to cut down on latency. You can be one of the first to try it out!

As long as you're using a PlayHT 2.0 voice with the PlayHT2.0-turbo engine, the new streaming API will be used by the SDK. All you need is to have Node.js installed. You can also try out the new streaming model using the Python SDK too.

Set Up

First set up the environment on a new folder. In the command line, write:

mkdir turboPlayHT
cd turboPlayHT
npm init -y

Next, install the SDK:

npm install --save playht

Let's Stream

Curious about the speed? Let's stream some sentences and see how quickly we get that first chunk of data for each one. Heads up: you'll need your credentials for PlayHT. Swap out the placeholders in the code.

Create a file named fastPlayHT.mjs with the content below.

import { createWriteStream } from "node:fs";
import * as PlayHT from "playht";

// Initialize PlayHT API
PlayHT.init({
  apiKey: "<YOUR_PLAY_HT_API_KEY>",
  userId: "<YOUR_PLAY_HT_USER_ID>",
});

const GenerationOptions = {
  voiceEngine: "PlayHT2.0-turbo",
  voiceId:
    "s3://voice-cloning-zero-shot/d9ff78ba-d016-47f6-b0ef-dd630f59414e/female-cs/manifest.json",
};

// Warm up the network caching and voice
const warmUpStream = await PlayHT.stream("warm up", GenerationOptions);
await new Promise((resolve, reject) => {
  warmUpStream.on("data", resolve);
  warmUpStream.on("error", reject);
});

const sentences = [
  "Hello, play support speaking. How can I help you?",
  "Please hold on a sec, uh Let me just, um, pull up your details real quick.",
  "Can you tell me your account email or, ah your phone number?",
  "Okay, there you are.",
  "So, what are you actually looking for in the upgrade? Any, uh, specific features or stuff that you’ve got your eye on?",
  "I’m sorry for the inconvenience, um, but we’ve had a few system updates lately.",
  "Is there a, um, particular reason you’re thinking of changing your current plan?",
  "Uh, just to clarify, you’re looking to upgrade to the premium package, right?",
  "If you could, um, provide me with the error message you received, I can help you better.",
  "Thank you for your patience. I’ll, ah, have this sorted out for you in just a moment.",
  "Were there any other, uh, issues or concerns you wanted to address today?",
  "Alright, your changes have been, um, saved. You should receive an email confirmation shortly.",
];

// Array to store the time to first bytes (TTFB) for each sentence
const TTFBs = [];

const streamAudio = async () => {
  const fileStream = createWriteStream("turbo-play.mp3");

  // Wait for file to opwn
  await new Promise((resolve, reject) => {
    fileStream.on("open", resolve);
    fileStream.on("error", reject);
  });

  for (let [i, sentence] of sentences.entries()) {
    // Start the timer
    const startTime = Date.now();

    const stream = await PlayHT.stream(sentence, GenerationOptions);

    let firstChunkReceived = false;
    stream.on("data", (chunk) => {
      if (!firstChunkReceived) {
        const TTFB = Date.now() - startTime; // Calculate TTFB
        console.log(`TTFB for sentence ${i}: ${TTFB}ms`);
        TTFBs.push(TTFB); // Store the TTFB in the array
        firstChunkReceived = true;
      }

      fileStream.write(chunk);
    });

    await new Promise((resolve, reject) => {
      stream.on("end", resolve);
      stream.on("error", reject);
    });
  }

  fileStream.end();

  // Calculate average TTFB
  const avgTTFB = TTFBs.reduce((sum, value) => sum + value, 0) / TTFBs.length;

  console.log(`Average TTFB: ${avgTTFB.toFixed(2)}ms`);

  // Calculate median TTFB
  const sortedTTFBs = [...TTFBs].sort((a, b) => a - b);
  const mid = Math.floor(sortedTTFBs.length / 2);
  const medianTTFB =
    sortedTTFBs.length % 2 === 0
      ? (sortedTTFBs[mid - 1] + sortedTTFBs[mid]) / 2
      : sortedTTFBs[mid];

  console.log(`Median TTFB: ${medianTTFB}ms`);

  process.exit(0);
};

await streamAudio().catch((error) => {
  console.error("Error:", error);
  process.exit(1);
});

The Reveal

Let's run this script:

node fastPlayHT.mjs

The script will print in the console the Time To First Byte (TTFB) for each sentence.

You should now find a turbo-play.mp3 file waiting for you. Give it a listen and hear the results of your venture.

Dive in, explore, and do let us know how it went. Happy streaming!