Skip to content

Commit

Permalink
Merge branch 'main' of github.com:matvp91/mixwave into feature/player…
Browse files Browse the repository at this point in the history
…-refactor
  • Loading branch information
matvp91 committed Dec 5, 2024
2 parents 39c10a7 + 8aabd4d commit a68b72c
Show file tree
Hide file tree
Showing 39 changed files with 1,594 additions and 439 deletions.
Binary file modified bun.lockb
Binary file not shown.
11 changes: 9 additions & 2 deletions packages/api/src/repositories/jobs.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,24 @@
import {
ffmpegQueue,
ffprobeQueue,
flowProducer,
outcomeQueue,
packageQueue,
pipelineQueue,
transcodeQueue,
} from "bolt";
import { Job as RawJob } from "bullmq";
import { FlowProducer, Job as RawJob } from "bullmq";
import { env } from "../env";
import { isRecordWithNumbers } from "../utils/type-guard";
import type { Job } from "../types";
import type { JobNode, JobState, Queue } from "bullmq";

const flowProducer = new FlowProducer({
connection: {
host: env.REDIS_HOST,
port: env.REDIS_PORT,
},
});

const allQueus = [
pipelineQueue,
transcodeQueue,
Expand Down
5 changes: 2 additions & 3 deletions packages/api/src/routes/jobs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import {
pipelineQueue,
transcodeQueue,
} from "bolt";
import { AudioCodec, VideoCodec } from "bolt";
import { Elysia, t } from "elysia";
import { auth } from "../auth";
import { DeliberateError } from "../errors";
Expand Down Expand Up @@ -43,14 +42,14 @@ const InputSchema = t.Union([
const StreamSchema = t.Union([
t.Object({
type: t.Literal("video"),
codec: t.Enum(VideoCodec),
codec: t.Union([t.Literal("h264"), t.Literal("vp9"), t.Literal("hevc")]),
height: t.Number(),
bitrate: t.Optional(t.Number({ description: "Bitrate in bps" })),
framerate: t.Optional(t.Number({ description: "Frames per second" })),
}),
t.Object({
type: t.Literal("audio"),
codec: t.Enum(AudioCodec),
codec: t.Union([t.Literal("aac"), t.Literal("ac3"), t.Literal("eac3")]),
bitrate: t.Optional(t.Number({ description: "Bitrate in bps" })),
language: t.Optional(t.String()),
channels: t.Optional(t.Number()),
Expand Down
4 changes: 3 additions & 1 deletion packages/app/src/components/Player.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ interface PlayerProps {

export function Player({ url, lang, metadata }: PlayerProps) {
const [hls] = useState(() => new Hls());
const controller = useController(hls);
const controller = useController(hls, {
multipleVideoElements: false,
});

useEffect(() => {
if (url) {
Expand Down
62 changes: 31 additions & 31 deletions packages/artisan/src/lib/default-values.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import { AudioCodec, VideoCodec } from "bolt";
import type { AudioCodec, VideoCodec } from "bolt";

const DEFAULT_AUDIO_BITRATE: Record<number, Record<AudioCodec, number>> = {
2: {
[AudioCodec.aac]: 128000,
[AudioCodec.ac3]: 192000,
[AudioCodec.eac3]: 96000,
aac: 128000,
ac3: 192000,
eac3: 96000,
},
6: {
[AudioCodec.aac]: 256000,
[AudioCodec.ac3]: 384000,
[AudioCodec.eac3]: 192000,
aac: 256000,
ac3: 384000,
eac3: 192000,
},
};

Expand All @@ -19,44 +19,44 @@ export function getDefaultAudioBitrate(channels: number, codec: AudioCodec) {

const DEFAULT_VIDEO_BITRATE: Record<number, Record<VideoCodec, number>> = {
144: {
[VideoCodec.h264]: 108000,
[VideoCodec.hevc]: 96000,
[VideoCodec.vp9]: 96000,
h264: 108000,
hevc: 96000,
vp9: 96000,
},
240: {
[VideoCodec.h264]: 242000,
[VideoCodec.hevc]: 151000,
[VideoCodec.vp9]: 151000,
h264: 242000,
hevc: 151000,
vp9: 151000,
},
360: {
[VideoCodec.h264]: 400000,
[VideoCodec.hevc]: 277000,
[VideoCodec.vp9]: 277000,
h264: 400000,
hevc: 277000,
vp9: 277000,
},
480: {
[VideoCodec.h264]: 1000000,
[VideoCodec.hevc]: 512000,
[VideoCodec.vp9]: 512000,
h264: 1000000,
hevc: 512000,
vp9: 512000,
},
720: {
[VideoCodec.h264]: 2000000,
[VideoCodec.hevc]: 1000000,
[VideoCodec.vp9]: 1000000,
h264: 2000000,
hevc: 1000000,
vp9: 1000000,
},
1080: {
[VideoCodec.h264]: 4000000,
[VideoCodec.hevc]: 2000000,
[VideoCodec.vp9]: 2000000,
h264: 4000000,
hevc: 2000000,
vp9: 2000000,
},
1440: {
[VideoCodec.h264]: 9000000,
[VideoCodec.hevc]: 6000000,
[VideoCodec.vp9]: 6000000,
h264: 9000000,
hevc: 6000000,
vp9: 6000000,
},
2160: {
[VideoCodec.h264]: 17000000,
[VideoCodec.hevc]: 12000000,
[VideoCodec.vp9]: 12000000,
h264: 17000000,
hevc: 12000000,
vp9: 12000000,
},
};

Expand Down
8 changes: 7 additions & 1 deletion packages/artisan/src/workers/ffprobe.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,14 @@ export const ffprobeCallback: WorkerCallback<
const stream = info.streams.find(
(stream) => stream.codec_type === "audio",
);

let language = info.format.tags?.["language"];
if (!language || typeof language === "number") {
language = undefined;
}

result.audio[input.path] = {
language: info.format.tags?.["language"] as string,
language,
channels: stream?.channels,
};
}
Expand Down
13 changes: 10 additions & 3 deletions packages/artisan/src/workers/package.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,16 +88,23 @@ async function handleStepInitial(job: Job<PackageData>, dir: WorkerDir) {
}

if (stream.type === "audio") {
packagerParams.push([
const params = [
`in=${inDir}/${key}`,
"stream=audio",
`init_segment=${file.name}/init.mp4`,
`segment_template=${file.name}/$Number$.m4a`,
`playlist_name=${file.name}/playlist.m3u8`,
`hls_group_id=${getGroupId(stream)}`,
`hls_name=${getName(stream)}`,
`language=${stream.language}`,
]);
];

if (stream.language !== "und") {
// TODO: We should use getLangCode here to figure out if we can pass a valid
// iso str, and leave it as-is when it is null.
params.push(`language=${stream.language}`);
}

packagerParams.push(params);
}

if (stream.type === "text") {
Expand Down
13 changes: 10 additions & 3 deletions packages/artisan/src/workers/transcode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import {
outcomeQueue,
waitForChildren,
} from "bolt";
import { by639_2T } from "iso-language-codes";
import { assert } from "shared/assert";
import { getLangCode } from "shared/lang";
import {
getDefaultAudioBitrate,
getDefaultVideoBitrate,
Expand Down Expand Up @@ -323,8 +323,8 @@ export function mergeInput(
const info = probeResult.audio[partial.path];
assert(info);

const language = partial.language ?? getLangCode(info.language);
assert(language, defaultReason("audio", "language"));
// Get the language code, if not found, we fallback to undecided.
const language = partial.language ?? getLangCode(info.language) ?? "und";

// Assume when no channel metadata is found, we'll fallback to 2.
const channels = partial.channels ?? info.channels ?? 2;
Expand Down Expand Up @@ -353,3 +353,10 @@ function defaultReason<T extends Stream["type"]>(
"You will have to provide it in the stream instead."
);
}

function getLangCode(value?: string) {
if (value && value in by639_2T) {
return value;
}
return null;
}
12 changes: 10 additions & 2 deletions packages/artisan/test/setup.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,17 @@
import { mock } from "bun:test";

mock.module("bullmq", () => ({
Queue: class {},
Worker: class {},
WaitingChildrenError: class {},
}));

process.env = {
NODE_ENV: "test",
TZ: "UTC",
S3_ENDPOINT: "s3-endpoint",
S3_REGION: "s3-region",
S3_ACCESS_KEY: "s3-access-key",
S3_SECRET_KEY: "s3-secret-key",
S3_BUCKET: "s3-bucket",
REDIS_HOST: "redis-host",
REDIS_PORT: "6379",
};
21 changes: 10 additions & 11 deletions packages/artisan/test/workers/transcode.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import "bun";
import { AudioCodec, VideoCodec } from "bolt";
import { describe, expect, test } from "bun:test";
import {
getMatches,
Expand Down Expand Up @@ -74,7 +73,7 @@ describe("merge stream", () => {
const stream = mergeStream(
{
type: "video",
codec: VideoCodec.h264,
codec: "h264",
height: 720,
},
{
Expand All @@ -90,7 +89,7 @@ describe("merge stream", () => {
const stream = mergeStream(
{
type: "video",
codec: VideoCodec.h264,
codec: "h264",
height: 1080,
},
{
Expand All @@ -107,7 +106,7 @@ describe("merge stream", () => {
const stream = mergeStream(
{
type: "video",
codec: VideoCodec.h264,
codec: "h264",
height: 480,
},
{
Expand All @@ -124,7 +123,7 @@ describe("merge stream", () => {
const stream = mergeStream(
{
type: "audio",
codec: AudioCodec.aac,
codec: "aac",
},
{
type: "audio",
Expand All @@ -143,34 +142,34 @@ describe("get list of matches", () => {
[
{
type: "video",
codec: VideoCodec.hevc,
codec: "hevc",
height: 1080,
},
{
type: "video",
codec: VideoCodec.h264,
codec: "h264",
height: 720,
},
{
type: "audio",
codec: AudioCodec.eac3,
codec: "eac3",
channels: 100,
bitrate: 1_000_000,
},
{
type: "audio",
codec: AudioCodec.ac3,
codec: "ac3",
channels: 6,
},
{
type: "audio",
codec: AudioCodec.aac,
codec: "aac",
channels: 2,
language: "eng",
},
{
type: "audio",
codec: AudioCodec.aac,
codec: "aac",
language: "nld",
},
],
Expand Down
6 changes: 0 additions & 6 deletions packages/bolt/src/add-to-queue.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,6 @@
import { randomUUID } from "crypto";
import { FlowProducer } from "bullmq";
import { connection } from "./env";
import type { Job, JobsOptions, Queue } from "bullmq";

export const flowProducer = new FlowProducer({
connection,
});

export const DEFAULT_SEGMENT_SIZE = 2.24;

export const DEFAULT_PACKAGE_NAME = "hls";
Expand Down
12 changes: 2 additions & 10 deletions packages/bolt/src/types.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,6 @@
export enum AudioCodec {
aac = "aac",
ac3 = "ac3",
eac3 = "eac3",
}
export type VideoCodec = "h264" | "vp9" | "hevc";

export enum VideoCodec {
h264 = "h264",
vp9 = "vp9",
hevc = "hevc",
}
export type AudioCodec = "aac" | "ac3" | "eac3";

export type PartialStream =
| {
Expand Down
8 changes: 6 additions & 2 deletions packages/player/src/react/hooks/useController.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
import { useCallback, useEffect, useRef, useState } from "react";
import { HlsFacade } from "..";
import type { HlsFacadeOptions } from "..";
import type Hls from "hls.js";

type MediaRefCallback = (media: HTMLMediaElement | null) => void;

export type Controller = ReturnType<typeof createController>;

export function useController(hls: Hls) {
const [facade] = useState<HlsFacade>(() => new HlsFacade(hls));
export function useController(
hls: Hls,
userOptions?: Partial<HlsFacadeOptions>,
) {
const [facade] = useState<HlsFacade>(() => new HlsFacade(hls, userOptions));
const lastMediaRef = useRef<HTMLMediaElement | null>(null);

useEffect(() => {
Expand Down
2 changes: 0 additions & 2 deletions packages/shared/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,8 @@
"lint": "tsc && eslint"
},
"dependencies": {
"@sinclair/typebox": "^0.32.34",
"dotenv": "^16.4.5",
"find-config": "^1.0.0",
"iso-language-codes": "^2.0.0",
"zod": "^3.23.8"
},
"devDependencies": {
Expand Down
Loading

0 comments on commit a68b72c

Please sign in to comment.