Node.js server that streams an infinite silence sound switches to streaming mew audio data receiving an event, and then returns to silence

Joined
Aug 16, 2024
Messages
1
Reaction score
0
To create a Node.js server that streams an infinite silence sound, switches to streaming actual audio data upon receiving an event, and then returns to silence after the event's audio data ends, steps:

Plan:
  1. Create an HTTP Server: Set up an HTTP server to handle incoming requests.
  2. Infinite Silence Sound: Stream silence sound infinitely when the request starts.
  3. Handle Audio Events: On receiving an appEvent.on('audio'), start streaming the audio data.
  4. Return to Silence: Once the audio data ends, go back to streaming silence.
  5. Keep the Request Open: Ensure the request stays open as long as the client is connected.
My Problem:
  1. switching between file streaming doesn't work
  2. silence sound always infinite play good but speech.mp3 doesn't work
    How to resolve switching between file stream for pipe to response ? This sevice must work like Radio
My Implementation:

JavaScript:
import express from 'express'
import * as fs from 'fs'
import path from 'path'
import { Readable } from 'stream'

const appEvent = new events.EventEmitter()

const silencePath = path.join(__dirname, 'silence.mp3')

// Helper function to generate silence sound
function silence() {
  const buffer = fs.readFileSync(silencePath) // Read file as Buffer
  return Readable.from(
    (async function* () {
      while (true) {
        yield buffer // Yield Buffer, not ArrayBuffer
      }
    })(),
  )
}

const app = express()

app.get('/stream', (req, res) => {
  // Example: Emit audio event to start streaming audio data
  setTimeout(() => {
    const speechPath = path.join(__dirname, 'speech.mp3')
    const speechStream = fs.createReadStream(speechPath)

    appEvent.emit('audio', speechStream)
  }, 5000)

  res.writeHead(200, {
    'Content-Type': 'audio/mpeg',
    'Transfer-Encoding': 'chunked',
    Connection: 'keep-alive',
  })

  let silenceStream = silence()
  silenceStream.pipe(res)

  let audioStream: fs.ReadStream
  let audioInProgress = false

  // Listen for audio event to switch to the audio stream
  appEvent.on('audio', (audioDataStream: fs.ReadStream) => {
    if (audioInProgress) return // Ignore if already playing audio

    audioInProgress = true
    silenceStream.unpipe(res)

    audioStream = audioDataStream
    audioStream.pipe(res)

    // When the audio finishes, return to silence
    audioStream.on('end', () => {
      silenceStream = silence()
      silenceStream.pipe(res)
      audioInProgress = false
    })
  })

  req.on('close', () => {
    if (audioStream) {
      audioStream.unpipe(res)
      audioStream.destroy()
    }
    silenceStream.unpipe(res)
  })
})

app.listen(3000, () => console.log(`Client side start on 3000 port http://localhost:3000`))
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,981
Messages
2,570,188
Members
46,731
Latest member
MarcyGipso

Latest Threads

Top