NextJS - Can't resolve 'child_process'
Closed this issue ยท 5 comments
osehmathias commented
In a very simple implementation:
"use client";
import { ElevenLabsClient, play } from "elevenlabs";
export default async function Audio(props: any) {
const elevenlabs = new ElevenLabsClient({
apiKey: "process.env.ELEVENLABS_API_KEY",
});
const audio = await elevenlabs.generate({
voice: "Rachel",
text: "We support two main models.",
model_id: "eleven_multilingual_v2",
});
await play(audio);
return <div>Placeholder</div>;
}
This error is persistent.
./node_modules/command-exists/lib/command-exists.js:3:0
Module not found: Can't resolve 'child_process'
https://nextjs.org/docs/messages/module-not-found
Import trace for requested module:
./node_modules/command-exists/index.js
./node_modules/elevenlabs/wrapper/play.js
./node_modules/elevenlabs/wrapper/index.js
./node_modules/elevenlabs/index.js
./components/Audio.tsx
./components/ChatMessageBubble.tsx
./components/ChatWindow.tsx
I can change the config every which way and it doesn't resolve the issue.
For example, in package.config, I can set:
"browser": {
"fs": false,
"child_process": false
},
However, then it shows the following error.
cannot destructure property 'signals' of '_os.constants' as it is undefined
These are the details of my project:
"engines": {
"node": ">=18"
},
"dependencies": {
...
"elevenlabs": "^0.2.2",
"next": "^14.0.1",
"react": "18.2.0",
"react-dom": "18.2.0",
...
},
sponrad commented
@osehmathias I see you closed this... did you figure it out? I'm hitting the same issue with nearly the same simple setup.
osehmathias commented
I closed it as I realised I ignorantly put this on the client side.
Put the ElevenLabs call in an API route then post to the route.
sponrad commented
Ahh of course. Thanks for responding back so fast saved me some time. Cheers
osehmathias commented
// app/api/tts/route.ts
import { ElevenLabsClient } from "elevenlabs";
import { NextResponse } from "next/server";
export async function POST(req) {
const { message } = await req.json();
const elevenlabs = new ElevenLabsClient({
apiKey: process.env.ELEVENLABS_API_KEY,
});
try {
const audio = await elevenlabs.generate({
voice: process.env.ELEVENLABS_VOICE_ID,
model_id: "eleven_turbo_v2",
voice_settings: {
similarity_boost: 0.5,
stability: 0.5,
use_speaker_boost: true,
},
text: message,
});
return new Response(audio, {
headers: { "Content-Type": "audio/mpeg" },
});
} catch (error) {
console.error(error);
return NextResponse.json(error, { status: error.statusCode });
}
}
// in your page / component
...
const audioRef = useRef<HTMLAudioElement>(new Audio());
...
const getAudioResponse = async (text) => {
const response = await fetch("/api/tts", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
message: text,
}),
});
return await response.blob();
}
const botVoiceResponse = await getAudioResponse(text);
const reader = new FileReader();
reader.readAsDataURL(botVoiceResponse);
reader.onload = () => {
if (audioRef.current) {
audioRef.current.src = reader.result as string;
}
};
....
return (
<audio ref={audioRef} hidden />
)
]
sponrad commented
@osehmathias this is an amazing simple working example, something like this should be in their documentation, thanks so much!