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:
Plan:
- Create an HTTP Server: Set up an HTTP server to handle incoming requests.
- Infinite Silence Sound: Stream silence sound infinitely when the request starts.
- Handle Audio Events: On receiving an appEvent.on('audio'), start streaming the audio data.
- Return to Silence: Once the audio data ends, go back to streaming silence.
- Keep the Request Open: Ensure the request stays open as long as the client is connected.
- switching between file streaming doesn't work
- 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
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`))