Blog

Come implementare il live streaming in Next.js

· Andrij Tkachenko · 7 min di lettura

Una finestra del browser con una persona in video e un ospite accanto, che trasmette a quattro finestre più piccole, in una qualcuno alza la mano e in un’altra qualcuno scrive

Una diretta sembra una sola funzione, e in un’app Next.js sono diverse. Qualcuno va in onda dal browser, o da un encoder come OBS. Tutti quelli che possono guardare lo vedono e lo sentono nello stesso momento, abbastanza vicini da fare una domanda e ricevere la risposta. Gli spettatori scrivono in una chat, reagiscono, e alcuni salgono sul palco con la propria fotocamera. E prima di tutto questo, la tua app deve decidere chi trasmette, chi guarda e chi viene a sapere che una diretta è iniziata.

Questo articolo passa in rassegna ogni parte che serve a un’app vera, con un esempio completo e funzionante: Live Lessons, il sito di lezioni dal vivo della nostra guida Next.js, dove insegnanti di cucina, musica e fitness vanno in diretta nelle loro lezioni, e gli studenti guardano, fanno domande e salgono sul palco. Puoi provarlo dal vivo: sii Mia e vai in diretta dal suo studio, poi apri la sua lezione in una finestra privata come Ava, una delle sue studentesse, per guardare e alzare la mano.

Cosa serve a una diretta

  • L’immagine in entrata. La fotocamera e il microfono dal browser, uno schermo condiviso con il suo audio, o un encoder via WHIP per scene e più fotocamere.
  • L’immagine in uscita, a molti, nello stesso momento. Una diretta il cui pubblico risponde passa per WebRTC, come le chiamate, attraverso server media che la inoltrano a ogni spettatore (come funzionano i server media). Le sue connessioni restano aperte per tutta la diretta, cosa che una funzione serverless non può tenere (perché, e cosa fare).
  • Chi trasmette e chi guarda. Una regola sul tuo server, con i tuoi dati: l’insegnante trasmette, gli studenti del corso guardano, e una lezione aperta la può vedere chiunque.
  • Uno studio e un player. Andare in diretta e chiudere, la fotocamera e lo schermo, la chat, le reazioni e quanti guardano.
  • Il palco. Uno spettatore alza la mano, l’insegnante lo invita, e tutti lo vedono accanto a sé.
  • Sapere cosa è in diretta. Elenchi delle dirette in corso che si aggiornano da soli, e un avviso a chi vuole saperlo.

Puoi costruire ciascuna di queste parti da solo, su WebRTC e server media tuoi. Oppure lasci che un cloud realtime gestisca i media, lo studio e il player, mentre il tuo server tiene l’unica parte davvero tua: la regola. È ciò che fa Live Lessons, con WordPlus Cloud.

L’esempio: lezioni dal vivo

Gli insegnanti hanno dei corsi, ognuno con le sue lezioni. Una lezione è aperta a tutti, o solo agli studenti del suo corso. Un insegnante va in diretta in una lezione dal suo studio, e gli studenti guardano sulla pagina della lezione. È un’app Next.js con App Router, Better Auth e Postgres, e la sua parte in tempo reale sta in pochi file. Cinque passi fanno le sue dirette.

1. Chi può guardare

Ogni lezione ha la sua diretta, con il nome del suo numero: lesson:7. Il sito le dichiara una volta sola, con quello schema, insieme alla regola:

lib/realtime.ts
realtime.streams(
    'lesson:{id}',
    async (user, { id }) => {
        const lesson = await lessonOf(id);
        if (!lesson) return false;
        const me = user === null ? null : String(user);
        if (me === lesson.teacher) return { role: 'host', quality: '1080p' };
        return (await mayWatch(me, lesson)) ? 'viewer' : false;
    },
    { stage: true, reactions: true },
);

L’insegnante è l’host, con l’immagine fino a 1080p. Chi mayWatch fa entrare è spettatore, e user è null per un visitatore che non ha effettuato l’accesso, così una lezione aperta non richiede un account. Tutti gli altri ricevono false. Le impostazioni ammettono ospiti sul palco e reazioni. La pagina della lezione chiede allo stesso mayWatch, quindi la pagina e la diretta non sono mai in disaccordo.

2. Dove gira la regola

Quando una pagina chiede di andare in diretta, o di guardare, chiede prima al server del sito, in un route handler:

app/api/realtime/calls/route.ts
import { currentUserId } from '@/lib/auth';
import { realtime } from '@/lib/realtime';

export async function POST(request: Request) {
    // JSON only, which a page of another site can't send here.
    if (!request.headers.get('content-type')?.includes('application/json')) {
        return new Response(null, { status: 415 });
    }
    const ask = await request.json();
    const user = await currentUserId();
    const pass = await realtime.authorizeCall(ask, user);
    return Response.json(pass);
}

È la stessa route da cui passano le videochiamate del sito di incontri (come implementare le videochiamate in Next.js). La regola gira con la sessione del sito, e la pagina riceve un pass per la diretta, firmato con il segreto dell’app, o il motivo per cui no. La route risponde con una richiesta breve, proprio ciò in cui l’hosting serverless dà il meglio.

3. Lo studio dell’insegnante

Un insegnante va in diretta da una pagina tutta sua, con dentro lo studio di WordPlus Cloud:

app/(site)/studio/[id]/page.tsx
<LiveStream
    name={roomOf(lesson.id)}
    view="studio-page"
    title={`${lesson.position}. ${lesson.title}`}
    url={`/lessons/${lesson.id}`}
    backUrl="/studio"
/>

Lo studio occupa l’altezza che la pagina gli dà: l’immagine grande quanto ci sta, con fotocamera, schermo, OBS e Go live sotto, e accanto, in schede, la chat, gli ospiti con le mani alzate, e la diretta con il link della lezione da condividere. Prima, la pagina controlla che chi chiede insegni la lezione, e manda chiunque altro alla lezione. All’accesso, un insegnante arriva all’elenco delle sue lezioni, ognuna a un clic dalla diretta.

4. La pagina della lezione

Gli studenti guardano dove si trova la lezione:

app/(site)/lessons/[id]/page.tsx
<LiveStream
    name={roomOf(lesson.id)}
    title={lesson.title}
    loginUrl="/signin"
    studioUrl={teaches ? `/studio/${lesson.id}` : undefined}
/>

Un solo elemento disegna il player e la sua chat. Prima dell’inizio della lezione lo dice, e parte non appena l’insegnante va in diretta, senza ricaricare. Uno studente che ha effettuato l’accesso può scrivere, reagire e premere Ask to join on stage. Un visitatore guarda e legge, con la strada per accedere. L’insegnante vede la strada per il suo studio sopra il player.

5. Cosa è in diretta, sempre aggiornato

WordPlus Cloud sa quali dirette sono in corso e quanti guardano ciascuna, quindi il sito non tiene alcuna tabella:

lib/realtime.ts
export async function liveNow(): Promise<Map<string, number>> {
    const live = new Map<string, number>();
    for (const stream of await realtime.listStreams()) {
        const lesson = lessonIn(stream.name);
        if (lesson) live.set(lesson, stream.viewers);
    }
    return live;
}

La home page elenca così le lezioni in diretta. Per tenere aggiornato quell’elenco anche sulle pagine già aperte, WordPlus Cloud manda al sito un webhook quando una diretta inizia e quando finisce, e il sito lo passa a una stanza a cui si unisce ogni pagina, anche quella di un visitatore:

lib/realtime.ts
realtime.room('live', { public: true });

realtime.on('stream.ended', async ({ stream }) => {
    if (lessonIn(stream)) await realtime.to('live').emit('changed');
});
app/(site)/live.tsx
export function LiveNow() {
    const router = useRouter();
    useRoom('live', { changed: () => router.refresh() });
    return null;
}

LiveNow sta nel layout, così ogni pagina richiede di nuovo i suoi elenchi al server, senza ricaricare. Il webhook stream.live fa lo stesso, e in più avvisa gli studenti del corso, e per una lezione aperta i follower del suo insegnante, con una notifica su qualunque pagina si trovino: «Mia is live: Your first tune».

Il palco, senza codice tuo

stage: true nella regola è tutto ciò che serve al palco. Mentre una lezione è in diretta, uno studente alza la mano dal player, l’insegnante la vede sotto Guests e preme Invite, e non appena lo studente accetta, tutti lo vedono accanto all’insegnante, con fotocamera e microfono. L’insegnante può silenziarlo o farlo scendere dal palco, e lo studente può lasciarlo da solo, tornando a guardare senza ricaricare.

Cosa è incluso

  • Dal browser o con OBS. Lo studio va in diretta con la fotocamera, con uno schermo e il suo audio, o con entrambi, oppure riceve OBS o qualsiasi encoder via WHIP.
  • Nello stesso momento. La diretta passa per WebRTC, così una domanda in chat arriva all’insegnante mentre è ancora sull’argomento.
  • Una chat curata. I moderatori fissano, eliminano, silenziano per un po’, allontanano e bannano, e la regola può nominare moderatore un assistente dell’insegnante: { role: 'viewer', mod: true }.
  • Togliere l’accesso. Quando uno studente lascia un corso, il sito lo toglie dalle lezioni in diretta di quel corso con realtime.stream(name).kick(), e da lì in poi la regola dice di no.

Provalo, poi costruisci il tuo

Nella demo dal vivo, gli insegnanti e gli studenti sono solo tuoi per un giorno, quindi qualunque cosa tu trasmetta o scriva, nessun altro la vede. Sotto ogni pagina, How this page works mostra il codice che la fa funzionare, un passo alla volta, con i valori della pagina che hai aperto.

La guida a Live Lessons costruisce l’intero sito, con ogni file della sua parte in tempo reale per intero, e le dirette in Next.js raccoglie tutti i modi per mettere una diretta nella tua app, anche con un’interfaccia tua.

WordPlus Cloud for Apps ha un prezzo in base alle connessioni simultanee, a partire da 1.000, con fatturazione mensile o annuale. Con 1.000 connessioni, le dirette sono senza conteggio fino a 50 spettatori contemporanei, e ogni 1.000 connessioni in più ne aggiungono 20. Oltre, ogni spettatore in più consuma un credito al minuto, conteggiato solo mentre la diretta è in onda. Scopri il live streaming per le app, o i prezzi per le app. Domande sulla tua integrazione? Scrivici.