https://github.com/ascorbic/chalkstream
chalkstream
https://github.com/ascorbic/chalkstream
Last synced: 7 months ago
JSON representation
chalkstream
- Host: GitHub
- URL: https://github.com/ascorbic/chalkstream
- Owner: ascorbic
- License: mit
- Created: 2023-07-24T18:38:26.000Z (over 2 years ago)
- Default Branch: main
- Last Pushed: 2023-11-17T16:53:10.000Z (about 2 years ago)
- Last Synced: 2025-06-13T11:51:07.760Z (8 months ago)
- Language: TypeScript
- Size: 352 KB
- Stars: 30
- Watchers: 2
- Forks: 1
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
Chalkstream is an open source, self-hosted live streaming "server" that runs on
serverless edge functions. You can stream right from the browser, with a public
link to share with your friends. It uses Netlify Edge Functions to ingest and
serve HLS streams, and the chunks are stored in Netlify Blobs. Control your own
data.
## How it works
HLS is a streaming protocol created by Apple that doesn't require a special
server to stream. It works by splitting the video into small chunks, and serving
them in a playlist. Chalkstream does this encoding in the browser using a
WebAssembly build of FFmpeg. This is a lot quicker if your browser natively
supports H.264 (most except Firefox). Otherwise your computer needs to be quite
fast if it is to handle real-time encoding. The chunks are then uploaded to
Netlify Blobs. Netlify Edge Functions handle the ingest and generating the
dynamic playlist.
**[See a demo](https://chalkstream-astro.netlify.app/)**
When you load the broadcast page it generates a random stream ID, and once you
start streaming you can share a page with the live stream. HLS streams can be
played in any modern browser, either natively or via Media Source Extensions and
Hls.js. Players such as Video.js and react-player make this easy - see
[the demo sites](https://github.com/ascorbic/chalkstream/tree/main/sites) for
examples.
## Usage
Chalkstream supports vanilla HTML+JS, plus React. For the vanilla version you
can either install it from npm and use it with a bundler or load it from a CDN
directly in the HTML page. For React, you can install it and import the
component.
### From a CDN
You can load the library directly from a CDN. This is the simplest way to get
started.
```html
import { ChalkStream } from "https://cdn.jsdelivr.net/npm/chalkstream";
const stream = new ChalkStream({
onReady: async (streamId) => {
document.getElementById("controls").hidden = false;
const playback = document.getElementById("playback-link");
playback.href = `/play/${streamId}`;
},
videoElement: document.getElementById("myself"),
onError: (error) => {
console.error(error);
},
});
const start = document.getElementById("start");
start.addEventListener("click", async () => {
if (!stream.isStreaming) {
stream.start();
start.textContent = "Stop";
} else {
stream.stop();
start.textContent = "Start";
}
});
stream.init();
```
### With a bundler
Install the package:
```sh
npm install chalkstream
```
Then import it:
```typescript
import { ChalkStream } from "chalkstream";
const stream = new ChalkStream({
onReady: async (streamId) => {
document.getElementById("controls").hidden = false;
const playback = document.getElementById("playback-link");
playback.href = `/play/${streamId}`;
},
videoElement: document.getElementById("myself"),
onError: (error) => {
console.error(error);
},
});
```
### With React
Install the package:
```sh
npm install chalkstream
```
Then import the component:
```typescript
import { ChalkStreamVideo, type ChalkStreamRef } from "chalkstream/react";
export const VideoPlayer = () => {
const [streamId, setStreamId] = useState(null);
const chalkstreamRef = useRef(null);
const togglePlayback = () => {
if (chalkstreamRef.current?.isStreaming) {
chalkstreamRef.current?.stop();
} else {
chalkstreamRef.current?.start();
}
};
return (
);
};
```
## Edge functions
However you build the site, you need to include three edge functions in the
`netlify/edge-functions` directory. These are `ingest`, `chunk` and `manifest`.
These just re-export the edge functions from the `chalkstream/edge` module.
Ensure that you have the correct config for each function so that the paths
match.
```typescript
// netlify/edge-functions/ingest.ts
import type { Context, Config } from "@netlify/edge-functions";
export { ingestHandler as default } from "https://esm.sh/chalkstream/edge";
export const config: Config = {
method: "PUT",
path: "/ingest/:session/:digest.ts",
};
```
```typescript
// netlify/edge-functions/chunk.ts
import type { Context, Config } from "@netlify/edge-functions";
export { chunkHandler as default } from "https://esm.sh/chalkstream/edge";
export const config: Config = {
method: "GET",
path: "/chunk/:session/:digest.ts",
};
```
```typescript
// netlify/edge-functions/manifest.ts
import type { Context, Config } from "@netlify/edge-functions";
export { manifestHandler as default } from "https://esm.sh/chalkstream/edge";
export const config: Config = {
method: "GET",
path: "/playlist/:session.m3u8",
};
```
## API
### `ChalkStream`
This is the main class. You either instantiate it, passing it a config object
and HTMLVideoElement, or you can use the React component which returns the
object in a ref.
#### `new ChalkStream(config: ChalkStreamConfig)`
## Security
By default, anybody can create a stream, and anybody can view it.
If you deploy the site yourself you should restrict access to prevent abuse. To
help with this, you can pass an "authorization" prop to the Chalkstream
consturctor, and it will be sent to the ingest endpoint as a bearer token. You
will need to check that header yourself at the moment!
Any completed stream can be viewed on-demand automatically. A stream is
considered complete if no chunks have been received for 30 seconds, but you can
resume streaming with the same session id and it will continue where it left
off.
All streams are public by default, and anyone can access the ingest endpoint. If
you want to do anything serious you should restrict access. The playback
endpoints require knowing the stream id, which is a hash of the session ID.
Anyone who knows the session ID can record to that stream, so don't share it!
Don't use your stream to record state secrets or recite your wallet seed phrase.
### 1. Deploy the site
Clone the repo, or use the button above to deploy the site to Netlify.
### 2. Customise the site, player etc
### Copyright
Copyright Matt Kane 2023. Chalkstream is released under the MIT license.