Skip to content

Commit

Permalink
Add TypeScript SDK
Browse files Browse the repository at this point in the history
  • Loading branch information
wkozyra95 committed Aug 19, 2024
1 parent 638e530 commit bab2f7f
Show file tree
Hide file tree
Showing 57 changed files with 7,306 additions and 0 deletions.
2 changes: 2 additions & 0 deletions ts/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
node_modules
dist
1 change: 1 addition & 0 deletions ts/@live-compositor/core/.eslintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
dist
32 changes: 32 additions & 0 deletions ts/@live-compositor/core/.eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{
"env": { },
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/eslint-recommended",
"plugin:@typescript-eslint/recommended",
"plugin:import/recommended",
"plugin:import/typescript",
"prettier"
],
"plugins": [
"prettier"
],
"parser": "@typescript-eslint/parser",
"rules": {
"prettier/prettier": ["error"],
"@typescript-eslint/no-explicit-any": [0, {}],
"no-constant-condition": [0],
"@typescript-eslint/no-unused-vars": [
"error",
{
"args": "all",
"argsIgnorePattern": "^_",
"caughtErrors": "all",
"caughtErrorsIgnorePattern": "^_",
"destructuredArrayIgnorePattern": "^_",
"varsIgnorePattern": "^_",
"ignoreRestSiblings": true
}
]
}
}
9 changes: 9 additions & 0 deletions ts/@live-compositor/core/.prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"printWidth": 100,
"tabWidth": 2,
"singleQuote": true,
"bracketSameLine": true,
"trailingComma": "es5",
"arrowParens": "avoid",
"endOfLine": "auto"
}
23 changes: 23 additions & 0 deletions ts/@live-compositor/core/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"name": "@live-compositor/core",
"version": "0.0.1",
"description": "",
"main": "dist/index.js",
"scripts": {
"lint": "eslint .",
"typecheck": "tsc --noEmit",
"watch": "tsc --watch",
"build": "tsc"
},
"author": "",
"license": "MIT",
"devDependencies": {
"@types/react-reconciler": "^0.28.8"
},
"dependencies": {
"react-reconciler": "^0.29.2"
},
"peerDependencies": {
"@live-compositor/core": "0.0.1"
}
}
117 changes: 117 additions & 0 deletions ts/@live-compositor/core/src/api.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
import { Api } from 'live-compositor';
import { ServerManager } from './serverManager';

export { Api };

export type ApiRequest = {
method: 'GET' | 'POST';
route: string;
body?: object;
};

export class ApiClient {
private serverManager: ServerManager;

constructor(serverManager: ServerManager) {
this.serverManager = serverManager;
}

public async updateScene(outputId: string, request: Api.UpdateOutputRequest): Promise<object> {
return this.serverManager.sendRequest({
method: 'POST',
route: `/api/output/${encodeURIComponent(outputId)}/update`,
body: request,
});
}

public async registerOutput(outptuId: string, request: Api.RegisterOutput): Promise<object> {
return this.serverManager.sendRequest({
method: 'POST',
route: `/api/output/${encodeURIComponent(outptuId)}/register`,
body: request,
});
}

public async unregisterOutput(outptuId: string): Promise<object> {
return this.serverManager.sendRequest({
method: 'POST',
route: `/api/output/${encodeURIComponent(outptuId)}/unregister`,
body: {},
});
}

public async registerInput(inputId: string, request: Api.RegisterInput): Promise<object> {
return this.serverManager.sendRequest({
method: 'POST',
route: `/api/input/${encodeURIComponent(inputId)}/register`,
body: request,
});
}

public async unregisterInput(inputId: string): Promise<object> {
return this.serverManager.sendRequest({
method: 'POST',
route: `/api/input/${encodeURIComponent(inputId)}/unregister`,
body: {},
});
}

public async registerShader(shaderId: string, request: Api.ShaderSpec): Promise<object> {
return this.serverManager.sendRequest({
method: 'POST',
route: `/api/shader/${encodeURIComponent(shaderId)}/register`,
body: request,
});
}

public async unregisterShader(shaderId: string): Promise<object> {
return this.serverManager.sendRequest({
method: 'POST',
route: `/api/shader/${encodeURIComponent(shaderId)}/unregister`,
body: {},
});
}

public async registerImage(imageId: string, request: Api.ImageSpec): Promise<object> {
return this.serverManager.sendRequest({
method: 'POST',
route: `/api/image/${encodeURIComponent(imageId)}/register`,
body: request,
});
}

public async unregisterImage(imageId: string): Promise<object> {
return this.serverManager.sendRequest({
method: 'POST',
route: `/api/image/${encodeURIComponent(imageId)}/unregister`,
body: {},
});
}

public async registerWebRenderer(
instanceId: string,
request: Api.WebRendererSpec
): Promise<object> {
return this.serverManager.sendRequest({
method: 'POST',
route: `/api/web-renderer/${encodeURIComponent(instanceId)}/register`,
body: request,
});
}

public async unregisterWebRenderer(instanceId: string): Promise<object> {
return this.serverManager.sendRequest({
method: 'POST',
route: `/api/web-renderer/${encodeURIComponent(instanceId)}/unregister`,
body: {},
});
}

public async start(): Promise<void> {
await this.serverManager.sendRequest({
method: 'POST',
route: `/api/start`,
body: {},
});
}
}
51 changes: 51 additions & 0 deletions ts/@live-compositor/core/src/api/input.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { Api } from '../api';
import { RegisterInput, Inputs } from 'live-compositor';

export function intoRegisterInput(input: RegisterInput): Api.RegisterInput {
if (input.type === 'mp4') {
return intoMp4RegisterInput(input);
} else if (input.type === 'rtp_stream') {
return intoRtpRegisterInput(input);
} else {
throw new Error(`Unknown input type ${(input as any).type}`);
}
}

function intoMp4RegisterInput(input: Inputs.RegisterMp4Input): Api.RegisterInput {
return {
type: 'mp4',
url: input.url,
path: input.path,
required: input.required,
offset_ms: input.offsetMs,
};
}

function intoRtpRegisterInput(input: Inputs.RegisterRtpInput): Api.RegisterInput {
return {
type: 'rtp_stream',
port: input.port,
transport_protocol: input.transportProtocol,
video: input.video,
audio: input.audio && intoInputAudio(input.audio),
required: input.required,
offset_ms: input.offsetMs,
};
}

function intoInputAudio(audio: Inputs.InputRtpAudioOptions): Api.InputRtpAudioOptions {
if (audio.decoder === 'opus') {
return {
decoder: 'opus',
forward_error_correction: audio.forwardErrorCorrection,
};
} else if (audio.decoder === 'aac') {
return {
decoder: 'aac',
audio_specific_config: audio.audioSpecificConfig,
rtp_mode: audio.rtpMode,
};
} else {
throw new Error(`Unknown audio decoder type: ${(audio as any).decoder}`);
}
}
87 changes: 87 additions & 0 deletions ts/@live-compositor/core/src/api/output.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import { RegisterOutput, Api, Outputs } from 'live-compositor';

export function intoRegisterOutput(
output: RegisterOutput,
initialVideo?: Api.Video
): Api.RegisterOutput {
if (output.type === 'rtp_stream') {
return intoRegisterRtpOutput(output, initialVideo);
} else {
throw new Error(`Unknown input type ${(output as any).type}`);
}
}

function intoRegisterRtpOutput(
output: Outputs.RegisterRtpOutput,
initialVideo?: Api.Video
): Api.RegisterOutput {
return {
type: 'rtp_stream',
port: output.port,
ip: output.ip,
transport_protocol: output.transportProtocol,
video: output.video && initialVideo && intoOutputRtpVideoOptions(output.video, initialVideo),
audio: output.audio && intoOutputRtpAudioOptions(output.audio),
};
}

function intoOutputRtpVideoOptions(
video: Outputs.OutputRtpVideoOptions,
initial: Api.Video
): Api.OutputRtpVideoOptions {
return {
resolution: video.resolution,
send_eos_when: video.sendEosWhen && intoOutputEosCondition(video.sendEosWhen),
encoder: intoVideoEncoderOptions(video.encoder),
initial,
};
}

function intoVideoEncoderOptions(encoder: Outputs.VideoEncoderOptions): Api.VideoEncoderOptions {
return {
type: 'ffmpeg_h264',
preset: encoder.preset,
ffmpeg_options: encoder.ffmpegOptions,
};
}

function intoOutputRtpAudioOptions(
audio: Outputs.OutputRtpAudioOptions
): Api.OutputRtpAudioOptions {
return {
send_eos_when: audio.sendEosWhen && intoOutputEosCondition(audio.sendEosWhen),
encoder: intoAudioEncoderOptions(audio.encoder),
initial: intoAudioInputsConfiguration(audio.initial),
};
}

function intoAudioEncoderOptions(encoder: Outputs.AudioEncoderOptions): Api.AudioEncoderOptions {
return {
type: 'opus',
preset: encoder.preset,
channels: encoder.channels,
};
}

export function intoAudioInputsConfiguration(audio: Outputs.AudioInputsConfiguration): Api.Audio {
return {
inputs: audio.inputs.map(input => ({
input_id: input.inputId,
volume: input.volume,
})),
};
}

function intoOutputEosCondition(condition: Outputs.OutputEndCondition): Api.OutputEndCondition {
if ('anyOf' in condition) {
return { any_of: condition.anyOf };
} else if ('allOf' in condition) {
return { all_of: condition.allOf };
} else if ('allInputs' in condition) {
return { all_inputs: condition.allInputs };
} else if ('anyInput' in condition) {
return { any_input: condition.anyInput };
} else {
throw new Error('Invalid "send_eos_when" value.');
}
}
Loading

0 comments on commit bab2f7f

Please sign in to comment.