Blog

So implementieren Sie Livestreaming in Next.js

· Andrij Tkachenko · 7 Min. Lesezeit

Ein Browserfenster mit einer Person im Video und einem Gast daneben, das an vier kleinere Fenster streamt, in einem hebt jemand die Hand, in einem anderen schreibt jemand

Ein Livestream sieht aus wie ein einzelnes Feature, doch in einer Next.js-App sind es mehrere. Eine Person geht im Browser live, oder mit einem Encoder wie OBS. Alle, die zuschauen dürfen, sehen und hören sie im gleichen Moment, nah genug, um eine Frage zu stellen und die Antwort zu bekommen. Zuschauer schreiben im Chat, reagieren, und manche kommen mit ihrer eigenen Kamera auf die Bühne. Und vor alledem muss Ihre App entscheiden, wer streamt, wer zuschaut und wer erfährt, dass ein Stream begonnen hat.

Dieser Beitrag geht jeden Teil durch, den eine echte App braucht, mit einem vollständigen, funktionierenden Beispiel: Live Lessons, die Website für Live-Kurse aus unserer Next.js-Anleitung. Lehrkräfte für Kochen, Musik und Fitness gehen dort in ihren Lektionen live, und die Lernenden schauen zu, fragen nach und kommen auf die Bühne. Sie können es live ausprobieren: Seien Sie Mia und gehen Sie in ihrem Studio live, dann öffnen Sie ihre Lektion in einem privaten Fenster als Ava, eine ihrer Schülerinnen, um zuzuschauen und die Hand zu heben.

Was Livestreaming braucht

  • Das Bild hinein. Kamera und Mikrofon aus dem Browser, ein geteilter Bildschirm mit seinem Ton, oder ein Encoder über WHIP für Szenen und mehrere Kameras.
  • Das Bild hinaus an viele, im gleichen Moment. Ein Stream, dessen Publikum antwortet, läuft über WebRTC wie ein Anruf, über Medienserver, die ihn an jeden Zuschauer weitergeben (wie Medienserver funktionieren). Seine Verbindungen bleiben den ganzen Stream über offen, und die kann eine Serverless-Funktion nicht halten (warum, und was sich dagegen tun lässt).
  • Wer streamt und wer zuschaut. Eine Regel auf Ihrem Server, mit Ihren eigenen Daten: Die Lehrkraft streamt, die Lernenden des Kurses schauen zu, und eine offene Lektion darf jeder sehen.
  • Ein Studio und ein Player. Livegehen und Beenden, Kamera und Bildschirm, der Chat, Reaktionen und wie viele zuschauen.
  • Die Bühne. Ein Zuschauer hebt die Hand, die Lehrkraft lädt ihn ein, und alle sehen ihn neben ihr.
  • Wissen, was live ist. Listen der Streams, die gerade live sind, die sich von selbst aktualisieren, und ein Hinweis an alle, die es wissen wollen.

Sie können all das selbst bauen, auf WebRTC und eigenen Medienservern. Oder Sie lassen eine Echtzeit-Cloud die Medien, das Studio und den Player betreiben, während Ihr Server den einen Teil behält, der wirklich Ihrer ist: die Regel. Genau das macht Live Lessons, über WordPlus Cloud.

Das Beispiel: Live-Kurse

Lehrkräfte haben Kurse, jeder mit seinen Lektionen. Eine Lektion ist für alle offen, oder nur für die Lernenden ihres Kurses. Eine Lehrkraft geht in einer Lektion aus ihrem Studio live, und die Lernenden schauen auf der Seite der Lektion zu. Es ist eine Next.js-App mit dem App Router, Better Auth und Postgres, und ihr Echtzeit-Teil besteht aus wenigen Dateien. Fünf Schritte machen ihre Streams.

1. Wer zuschauen darf

Jede Lektion hat einen Stream, benannt nach ihrer Nummer: lesson:7. Die Website deklariert sie einmal, nach diesem Muster, mit der Regel:

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 },
);

Die Lehrkraft ist der Host, mit dem Bild in bis zu 1080p. Wen mayWatch hereinlässt, schaut zu, und user ist null für einen Besucher, der nicht angemeldet ist, sodass eine offene Lektion kein Konto braucht. Alle anderen bekommen false. Die Einstellungen lassen Gäste auf die Bühne und erlauben Reaktionen. Die Seite der Lektion fragt dasselbe mayWatch, also sind sich Seite und Stream nie uneinig.

2. Wo die Regel läuft

Wenn eine Seite livegehen oder zuschauen will, fragt sie zuerst den eigenen Server der Website, in einem 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);
}

Es ist dieselbe Route, über die auch die Videoanrufe der Dating-Website laufen (so implementieren Sie Videoanrufe in Next.js). Die Regel läuft mit der eigenen Sitzung der Website, und die Seite bekommt einen Pass für den Stream, signiert mit dem Secret der App, oder den Grund, warum nicht. Die Route antwortet in einer kurzen Anfrage, und genau darin ist Serverless-Hosting gut.

3. Das Studio der Lehrkraft

Eine Lehrkraft geht auf einer eigenen Seite live, mit dem Studio von WordPlus Cloud darin:

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"
/>

Das Studio füllt die Höhe, die die Seite ihm gibt: das Bild so groß wie möglich, darunter Kamera, Bildschirm, OBS und Go live, und daneben, in Tabs, der Chat, die Gäste mit den gehobenen Händen und der Stream mit dem Link zur Lektion zum Teilen. Vorher prüft die Seite, dass die fragende Person die Lektion unterrichtet, und schickt alle anderen zur Lektion. Nach der Anmeldung landet eine Lehrkraft bei einer Liste ihrer Lektionen, jede einen Klick vom Livegehen entfernt.

4. Die Seite der Lektion

Die Lernenden schauen dort zu, wo die Lektion ist:

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

Ein Element zeichnet den Player und seinen Chat. Bevor die Lektion beginnt, sagt es das, und es spielt, sobald die Lehrkraft live geht, ohne Neuladen. Wer angemeldet ist, kann schreiben, reagieren und Ask to join on stage drücken. Ein Besucher schaut zu und liest mit, und sieht, wie er sich anmeldet. Die Lehrkraft sieht über dem Player den Weg in ihr Studio.

5. Was live ist, immer aktuell

WordPlus Cloud weiß, welche Streams live sind und wie viele jeweils zuschauen, also führt die Website keine Tabelle dafür:

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;
}

Die Startseite listet daraus die Lektionen, die gerade live sind. Damit diese Liste auch auf bereits geöffneten Seiten aktuell bleibt, schickt WordPlus Cloud der Website einen Webhook, wenn ein Stream live geht und wenn er endet, und die Website gibt ihn an einen Raum weiter, dem jede Seite beitritt, auch die eines Besuchers:

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 steht im Layout, sodass jede Seite den Server erneut nach ihren Listen fragt, ohne Neuladen. Der Webhook stream.live macht dasselbe und benachrichtigt außerdem die Lernenden des Kurses, bei einer offenen Lektion auch die Follower der Lehrkraft, auf welcher Seite sie auch gerade sind: „Mia is live: Your first tune“.

Die Bühne, ohne eigenen Code

stage: true in der Regel ist alles, was die Bühne braucht. Während eine Lektion live ist, hebt jemand im Player die Hand, die Lehrkraft sieht es unter Guests und drückt Invite, und sobald die Person annimmt, sehen alle sie neben der Lehrkraft, mit Kamera und Mikrofon. Die Lehrkraft kann sie stummschalten oder von der Bühne nehmen, und sie kann die Bühne selbst verlassen und schaut dann wieder zu, ohne Neuladen.

Was dazugehört

  • Aus dem Browser oder mit OBS. Das Studio geht mit der Kamera live, mit einem Bildschirm samt Ton oder mit beidem, oder nimmt OBS oder jeden anderen Encoder über WHIP an.
  • Im gleichen Moment. Der Stream läuft über WebRTC, also erreicht eine Frage im Chat die Lehrkraft, während sie noch beim Thema ist.
  • Ein Chat, der gepflegt wird. Moderatoren heften an, löschen, schalten für eine Weile stumm, entfernen und sperren, und die Regel kann eine Assistenz der Lehrkraft zur Moderation machen: { role: 'viewer', mod: true }.
  • Zugang entziehen. Verlässt jemand einen Kurs, nimmt die Website die Person mit realtime.stream(name).kick() aus dessen gerade laufenden Lektionen, und ab dann sagt die Regel Nein.

Ausprobieren, dann selbst bauen

In der Live-Demo gehören die Lehrkräfte und Lernenden einen Tag lang nur Ihnen: Was Sie dort streamen oder schreiben, sieht sonst niemand. Unter jeder Seite zeigt How this page works Schritt für Schritt den Code, der sie erzeugt, mit den Werten der Seite, die Sie gerade geöffnet haben.

Die Anleitung zu Live Lessons baut die ganze Website auf, mit jeder Datei ihres Echtzeit-Teils in voller Länge, und Livestreams in Next.js zeigt jeden Weg, einen Stream in Ihre eigene App zu bringen, eine eigene Oberfläche eingeschlossen.

Für WordPlus Cloud for Apps gelten Preise nach gleichzeitigen Verbindungen, ab 1.000, monatlich oder jährlich abgerechnet. Mit 1.000 Verbindungen sind Livestreams bis zu 50 Zuschauern gleichzeitig ohne Abrechnung, und mit jeweils 1.000 weiteren Verbindungen kommen 20 hinzu. Darüber verbraucht jeder weitere Zuschauer ein Credit pro Minute, gezählt nur, solange der Stream live ist. Sehen Sie sich Livestreaming für Apps an, oder werfen Sie einen Blick auf die Preise für Apps. Fragen zu Ihrer Integration? Schreiben Sie uns.