mirror of
https://github.com/nestriness/nestri.git
synced 2025-12-12 16:55:37 +02:00
✨ feat: Host a relay on Hetzner (#114)
We are hosting a [MoQ](https://quic.video) relay on a remote (bare metal) server on Hetzner With a lot of help from @victorpahuus
This commit is contained in:
37
packages/moq/media/mp4/index.ts
Normal file
37
packages/moq/media/mp4/index.ts
Normal file
@@ -0,0 +1,37 @@
|
||||
// Rename some stuff so it's on brand.
|
||||
// We need a separate file so this file can use the rename too.
|
||||
import * as MP4 from "./rename"
|
||||
export * from "./rename"
|
||||
|
||||
export * from "./parser"
|
||||
|
||||
export function isAudioTrack(track: MP4.Track): track is MP4.AudioTrack {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
||||
return (track as MP4.AudioTrack).audio !== undefined
|
||||
}
|
||||
|
||||
export function isVideoTrack(track: MP4.Track): track is MP4.VideoTrack {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
||||
return (track as MP4.VideoTrack).video !== undefined
|
||||
}
|
||||
|
||||
// TODO contribute to mp4box
|
||||
MP4.BoxParser.dOpsBox.prototype.write = function (stream: MP4.Stream) {
|
||||
this.size = this.ChannelMappingFamily === 0 ? 11 : 13 + this.ChannelMapping!.length
|
||||
this.writeHeader(stream)
|
||||
|
||||
stream.writeUint8(this.Version)
|
||||
stream.writeUint8(this.OutputChannelCount)
|
||||
stream.writeUint16(this.PreSkip)
|
||||
stream.writeUint32(this.InputSampleRate)
|
||||
stream.writeInt16(this.OutputGain)
|
||||
stream.writeUint8(this.ChannelMappingFamily)
|
||||
|
||||
if (this.ChannelMappingFamily !== 0) {
|
||||
stream.writeUint8(this.StreamCount!)
|
||||
stream.writeUint8(this.CoupledCount!)
|
||||
for (const mapping of this.ChannelMapping!) {
|
||||
stream.writeUint8(mapping)
|
||||
}
|
||||
}
|
||||
}
|
||||
71
packages/moq/media/mp4/parser.ts
Normal file
71
packages/moq/media/mp4/parser.ts
Normal file
@@ -0,0 +1,71 @@
|
||||
import * as MP4 from "./index"
|
||||
|
||||
export interface Frame {
|
||||
track: MP4.Track // The track this frame belongs to
|
||||
sample: MP4.Sample // The actual sample contain the frame data
|
||||
}
|
||||
|
||||
// Decode a MP4 container into individual samples.
|
||||
export class Parser {
|
||||
info!: MP4.Info
|
||||
|
||||
#mp4 = MP4.New()
|
||||
#offset = 0
|
||||
|
||||
#samples: Array<Frame> = []
|
||||
|
||||
constructor(init: Uint8Array) {
|
||||
this.#mp4.onError = (err) => {
|
||||
console.error("MP4 error", err)
|
||||
}
|
||||
|
||||
this.#mp4.onReady = (info: MP4.Info) => {
|
||||
this.info = info
|
||||
|
||||
// Extract all of the tracks, because we don't know if it's audio or video.
|
||||
for (const track of info.tracks) {
|
||||
this.#mp4.setExtractionOptions(track.id, track, { nbSamples: 1 })
|
||||
}
|
||||
}
|
||||
|
||||
this.#mp4.onSamples = (_track_id: number, track: MP4.Track, samples: MP4.Sample[]) => {
|
||||
for (const sample of samples) {
|
||||
this.#samples.push({ track, sample })
|
||||
}
|
||||
}
|
||||
|
||||
this.#mp4.start()
|
||||
|
||||
// For some reason we need to modify the underlying ArrayBuffer with offset
|
||||
const copy = new Uint8Array(init)
|
||||
const buffer = copy.buffer as MP4.ArrayBuffer
|
||||
buffer.fileStart = this.#offset
|
||||
|
||||
this.#mp4.appendBuffer(buffer)
|
||||
this.#offset += buffer.byteLength
|
||||
this.#mp4.flush()
|
||||
|
||||
if (!this.info) {
|
||||
throw new Error("could not parse MP4 info")
|
||||
}
|
||||
}
|
||||
|
||||
decode(chunk: Uint8Array): Array<Frame> {
|
||||
const copy = new Uint8Array(chunk)
|
||||
|
||||
// For some reason we need to modify the underlying ArrayBuffer with offset
|
||||
const buffer = copy.buffer as MP4.ArrayBuffer
|
||||
buffer.fileStart = this.#offset
|
||||
|
||||
// Parse the data
|
||||
this.#mp4.appendBuffer(buffer)
|
||||
this.#mp4.flush()
|
||||
|
||||
this.#offset += buffer.byteLength
|
||||
|
||||
const samples = [...this.#samples]
|
||||
this.#samples.length = 0
|
||||
|
||||
return samples
|
||||
}
|
||||
}
|
||||
13
packages/moq/media/mp4/rename.ts
Normal file
13
packages/moq/media/mp4/rename.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
// Rename some stuff so it's on brand.
|
||||
export { createFile as New, DataStream as Stream, ISOFile, BoxParser, Log } from "mp4box"
|
||||
|
||||
export type {
|
||||
MP4ArrayBuffer as ArrayBuffer,
|
||||
MP4Info as Info,
|
||||
MP4Track as Track,
|
||||
MP4AudioTrack as AudioTrack,
|
||||
MP4VideoTrack as VideoTrack,
|
||||
Sample,
|
||||
TrackOptions,
|
||||
SampleOptions,
|
||||
} from "mp4box"
|
||||
Reference in New Issue
Block a user