build: prepare
@ -1,16 +0,0 @@
|
|||||||
# Editor configuration, see https://editorconfig.org
|
|
||||||
root = true
|
|
||||||
|
|
||||||
[*]
|
|
||||||
charset = utf-8
|
|
||||||
indent_style = space
|
|
||||||
indent_size = 2
|
|
||||||
insert_final_newline = true
|
|
||||||
trim_trailing_whitespace = true
|
|
||||||
|
|
||||||
[*.ts]
|
|
||||||
quote_type = single
|
|
||||||
|
|
||||||
[*.md]
|
|
||||||
max_line_length = off
|
|
||||||
trim_trailing_whitespace = false
|
|
42
apps/angular-app/.gitignore
vendored
@ -1,42 +0,0 @@
|
|||||||
# See http://help.github.com/ignore-files/ for more about ignoring files.
|
|
||||||
|
|
||||||
# Compiled output
|
|
||||||
/dist
|
|
||||||
/tmp
|
|
||||||
/out-tsc
|
|
||||||
/bazel-out
|
|
||||||
|
|
||||||
# Node
|
|
||||||
/node_modules
|
|
||||||
npm-debug.log
|
|
||||||
yarn-error.log
|
|
||||||
|
|
||||||
# IDEs and editors
|
|
||||||
.idea/
|
|
||||||
.project
|
|
||||||
.classpath
|
|
||||||
.c9/
|
|
||||||
*.launch
|
|
||||||
.settings/
|
|
||||||
*.sublime-workspace
|
|
||||||
|
|
||||||
# Visual Studio Code
|
|
||||||
.vscode/*
|
|
||||||
!.vscode/settings.json
|
|
||||||
!.vscode/tasks.json
|
|
||||||
!.vscode/launch.json
|
|
||||||
!.vscode/extensions.json
|
|
||||||
.history/*
|
|
||||||
|
|
||||||
# Miscellaneous
|
|
||||||
/.angular/cache
|
|
||||||
.sass-cache/
|
|
||||||
/connect.lock
|
|
||||||
/coverage
|
|
||||||
/libpeerconnection.log
|
|
||||||
testem.log
|
|
||||||
/typings
|
|
||||||
|
|
||||||
# System files
|
|
||||||
.DS_Store
|
|
||||||
Thumbs.db
|
|
4
apps/angular-app/.vscode/extensions.json
vendored
@ -1,4 +0,0 @@
|
|||||||
{
|
|
||||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=827846
|
|
||||||
"recommendations": ["angular.ng-template"]
|
|
||||||
}
|
|
20
apps/angular-app/.vscode/launch.json
vendored
@ -1,20 +0,0 @@
|
|||||||
{
|
|
||||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
|
||||||
"version": "0.2.0",
|
|
||||||
"configurations": [
|
|
||||||
{
|
|
||||||
"name": "ng serve",
|
|
||||||
"type": "chrome",
|
|
||||||
"request": "launch",
|
|
||||||
"preLaunchTask": "npm: start",
|
|
||||||
"url": "http://localhost:4200/"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "ng test",
|
|
||||||
"type": "chrome",
|
|
||||||
"request": "launch",
|
|
||||||
"preLaunchTask": "npm: test",
|
|
||||||
"url": "http://localhost:9876/debug.html"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
42
apps/angular-app/.vscode/tasks.json
vendored
@ -1,42 +0,0 @@
|
|||||||
{
|
|
||||||
// For more information, visit: https://go.microsoft.com/fwlink/?LinkId=733558
|
|
||||||
"version": "2.0.0",
|
|
||||||
"tasks": [
|
|
||||||
{
|
|
||||||
"type": "npm",
|
|
||||||
"script": "start",
|
|
||||||
"isBackground": true,
|
|
||||||
"problemMatcher": {
|
|
||||||
"owner": "typescript",
|
|
||||||
"pattern": "$tsc",
|
|
||||||
"background": {
|
|
||||||
"activeOnStart": true,
|
|
||||||
"beginsPattern": {
|
|
||||||
"regexp": "(.*?)"
|
|
||||||
},
|
|
||||||
"endsPattern": {
|
|
||||||
"regexp": "bundle generation complete"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "npm",
|
|
||||||
"script": "test",
|
|
||||||
"isBackground": true,
|
|
||||||
"problemMatcher": {
|
|
||||||
"owner": "typescript",
|
|
||||||
"pattern": "$tsc",
|
|
||||||
"background": {
|
|
||||||
"activeOnStart": true,
|
|
||||||
"beginsPattern": {
|
|
||||||
"regexp": "(.*?)"
|
|
||||||
},
|
|
||||||
"endsPattern": {
|
|
||||||
"regexp": "bundle generation complete"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
@ -1,27 +0,0 @@
|
|||||||
# AngularApp
|
|
||||||
|
|
||||||
This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 17.0.7.
|
|
||||||
|
|
||||||
## Development server
|
|
||||||
|
|
||||||
Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The application will automatically reload if you change any of the source files.
|
|
||||||
|
|
||||||
## Code scaffolding
|
|
||||||
|
|
||||||
Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module`.
|
|
||||||
|
|
||||||
## Build
|
|
||||||
|
|
||||||
Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory.
|
|
||||||
|
|
||||||
## Running unit tests
|
|
||||||
|
|
||||||
Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io).
|
|
||||||
|
|
||||||
## Running end-to-end tests
|
|
||||||
|
|
||||||
Run `ng e2e` to execute the end-to-end tests via a platform of your choice. To use this command, you need to first add a package that implements end-to-end testing capabilities.
|
|
||||||
|
|
||||||
## Further help
|
|
||||||
|
|
||||||
To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI Overview and Command Reference](https://angular.io/cli) page.
|
|
@ -1,95 +0,0 @@
|
|||||||
{
|
|
||||||
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
|
|
||||||
"version": 1,
|
|
||||||
"newProjectRoot": "projects",
|
|
||||||
"projects": {
|
|
||||||
"angular-app": {
|
|
||||||
"projectType": "application",
|
|
||||||
"schematics": {},
|
|
||||||
"root": "",
|
|
||||||
"sourceRoot": "src",
|
|
||||||
"prefix": "app",
|
|
||||||
"architect": {
|
|
||||||
"build": {
|
|
||||||
"builder": "@angular-devkit/build-angular:application",
|
|
||||||
"options": {
|
|
||||||
"outputPath": "dist/angular-app",
|
|
||||||
"index": "src/index.html",
|
|
||||||
"browser": "src/main.ts",
|
|
||||||
"polyfills": [
|
|
||||||
"zone.js"
|
|
||||||
],
|
|
||||||
"tsConfig": "tsconfig.app.json",
|
|
||||||
"assets": [
|
|
||||||
"src/favicon.ico",
|
|
||||||
"src/assets"
|
|
||||||
],
|
|
||||||
"styles": [
|
|
||||||
"src/styles.css"
|
|
||||||
],
|
|
||||||
"scripts": []
|
|
||||||
},
|
|
||||||
"configurations": {
|
|
||||||
"production": {
|
|
||||||
"budgets": [
|
|
||||||
{
|
|
||||||
"type": "initial",
|
|
||||||
"maximumWarning": "500kb",
|
|
||||||
"maximumError": "1mb"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "anyComponentStyle",
|
|
||||||
"maximumWarning": "2kb",
|
|
||||||
"maximumError": "4kb"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"outputHashing": "all"
|
|
||||||
},
|
|
||||||
"development": {
|
|
||||||
"optimization": false,
|
|
||||||
"extractLicenses": false,
|
|
||||||
"sourceMap": true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"defaultConfiguration": "production"
|
|
||||||
},
|
|
||||||
"serve": {
|
|
||||||
"builder": "@angular-devkit/build-angular:dev-server",
|
|
||||||
"configurations": {
|
|
||||||
"production": {
|
|
||||||
"buildTarget": "angular-app:build:production"
|
|
||||||
},
|
|
||||||
"development": {
|
|
||||||
"buildTarget": "angular-app:build:development"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"defaultConfiguration": "development"
|
|
||||||
},
|
|
||||||
"extract-i18n": {
|
|
||||||
"builder": "@angular-devkit/build-angular:extract-i18n",
|
|
||||||
"options": {
|
|
||||||
"buildTarget": "angular-app:build"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"test": {
|
|
||||||
"builder": "@angular-devkit/build-angular:karma",
|
|
||||||
"options": {
|
|
||||||
"polyfills": [
|
|
||||||
"zone.js",
|
|
||||||
"zone.js/testing"
|
|
||||||
],
|
|
||||||
"tsConfig": "tsconfig.spec.json",
|
|
||||||
"assets": [
|
|
||||||
"src/favicon.ico",
|
|
||||||
"src/assets"
|
|
||||||
],
|
|
||||||
"styles": [
|
|
||||||
"src/styles.css"
|
|
||||||
],
|
|
||||||
"scripts": []
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,40 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "angular-app",
|
|
||||||
"version": "0.0.0",
|
|
||||||
"scripts": {
|
|
||||||
"ng": "ng",
|
|
||||||
"start": "ng serve",
|
|
||||||
"build": "ng build",
|
|
||||||
"watch": "ng build --watch --configuration development",
|
|
||||||
"test": "ng test"
|
|
||||||
},
|
|
||||||
"private": true,
|
|
||||||
"dependencies": {
|
|
||||||
"@angular/animations": "^17.0.0",
|
|
||||||
"@angular/common": "^17.0.0",
|
|
||||||
"@angular/compiler": "^17.0.0",
|
|
||||||
"@angular/core": "^17.0.0",
|
|
||||||
"@angular/forms": "^17.0.0",
|
|
||||||
"@angular/platform-browser": "^17.0.0",
|
|
||||||
"@angular/platform-browser-dynamic": "^17.0.0",
|
|
||||||
"@angular/router": "^17.0.0",
|
|
||||||
"@ffmpeg/ffmpeg": "*",
|
|
||||||
"@ffmpeg/util": "*",
|
|
||||||
"rxjs": "~7.8.0",
|
|
||||||
"tslib": "^2.3.0",
|
|
||||||
"zone.js": "~0.14.2"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"@angular-devkit/build-angular": "^17.0.7",
|
|
||||||
"@angular/cli": "^17.0.7",
|
|
||||||
"@angular/compiler-cli": "^17.0.0",
|
|
||||||
"@types/jasmine": "~5.1.0",
|
|
||||||
"jasmine-core": "~5.1.0",
|
|
||||||
"karma": "~6.4.0",
|
|
||||||
"karma-chrome-launcher": "~3.2.0",
|
|
||||||
"karma-coverage": "~2.2.0",
|
|
||||||
"karma-jasmine": "~5.1.0",
|
|
||||||
"karma-jasmine-html-reporter": "~2.1.0",
|
|
||||||
"typescript": "~5.2.2"
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,111 +0,0 @@
|
|||||||
<!-- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -->
|
|
||||||
<!-- * * * * * * * * * * * The content below * * * * * * * * * * * -->
|
|
||||||
<!-- * * * * * * * * * * is only a placeholder * * * * * * * * * * -->
|
|
||||||
<!-- * * * * * * * * * * and can be replaced. * * * * * * * * * * -->
|
|
||||||
<!-- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -->
|
|
||||||
<!-- * * * * * * * * * Delete the template below * * * * * * * * * -->
|
|
||||||
<!-- * * * * * * * to get started with your project! * * * * * * * -->
|
|
||||||
<!-- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -->
|
|
||||||
|
|
||||||
<style>
|
|
||||||
:host {
|
|
||||||
--bright-blue: oklch(51.01% 0.274 263.83);
|
|
||||||
--electric-violet: oklch(53.18% 0.28 296.97);
|
|
||||||
--french-violet: oklch(47.66% 0.246 305.88);
|
|
||||||
--vivid-pink: oklch(69.02% 0.277 332.77);
|
|
||||||
--hot-red: oklch(61.42% 0.238 15.34);
|
|
||||||
--orange-red: oklch(63.32% 0.24 31.68);
|
|
||||||
|
|
||||||
--gray-900: oklch(19.37% 0.006 300.98);
|
|
||||||
--gray-700: oklch(36.98% 0.014 302.71);
|
|
||||||
--gray-400: oklch(70.9% 0.015 304.04);
|
|
||||||
|
|
||||||
--red-to-pink-to-purple-vertical-gradient: linear-gradient(
|
|
||||||
180deg,
|
|
||||||
var(--orange-red) 0%,
|
|
||||||
var(--vivid-pink) 50%,
|
|
||||||
var(--electric-violet) 100%
|
|
||||||
);
|
|
||||||
|
|
||||||
--red-to-pink-to-purple-horizontal-gradient: linear-gradient(
|
|
||||||
90deg,
|
|
||||||
var(--orange-red) 0%,
|
|
||||||
var(--vivid-pink) 50%,
|
|
||||||
var(--electric-violet) 100%
|
|
||||||
);
|
|
||||||
|
|
||||||
--pill-accent: var(--bright-blue);
|
|
||||||
|
|
||||||
font-family: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
|
|
||||||
Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji",
|
|
||||||
"Segoe UI Symbol";
|
|
||||||
box-sizing: border-box;
|
|
||||||
-webkit-font-smoothing: antialiased;
|
|
||||||
-moz-osx-font-smoothing: grayscale;
|
|
||||||
}
|
|
||||||
|
|
||||||
h1 {
|
|
||||||
font-size: 3.125rem;
|
|
||||||
color: var(--gray-900);
|
|
||||||
font-weight: 500;
|
|
||||||
line-height: 100%;
|
|
||||||
letter-spacing: -0.125rem;
|
|
||||||
margin: 0;
|
|
||||||
font-family: "Inter Tight", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
|
|
||||||
Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji",
|
|
||||||
"Segoe UI Symbol";
|
|
||||||
}
|
|
||||||
|
|
||||||
p {
|
|
||||||
margin: 0;
|
|
||||||
color: var(--gray-700);
|
|
||||||
}
|
|
||||||
|
|
||||||
main {
|
|
||||||
width: 100%;
|
|
||||||
min-height: 100%;
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
padding: 1rem;
|
|
||||||
box-sizing: inherit;
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media screen and (max-width: 650px) {
|
|
||||||
.content {
|
|
||||||
flex-direction: column;
|
|
||||||
width: max-content;
|
|
||||||
}
|
|
||||||
|
|
||||||
.divider {
|
|
||||||
height: 1px;
|
|
||||||
width: 100%;
|
|
||||||
background: var(--red-to-pink-to-purple-horizontal-gradient);
|
|
||||||
margin-block: 1.5rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<main class="main">
|
|
||||||
<div *ngIf="loaded">
|
|
||||||
<video src="{{ videoURL }}" controls></video>
|
|
||||||
<br />
|
|
||||||
<button (click)="transcode()">Transcode avi to mp4</button>
|
|
||||||
<p>{{ message }}</p>
|
|
||||||
</div>
|
|
||||||
<div *ngIf="!loaded">
|
|
||||||
<button (click)="load()">Load ffmpeg-core</button>
|
|
||||||
</div>
|
|
||||||
</main>
|
|
||||||
|
|
||||||
<!-- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -->
|
|
||||||
<!-- * * * * * * * * * * * The content above * * * * * * * * * * * * -->
|
|
||||||
<!-- * * * * * * * * * * is only a placeholder * * * * * * * * * * * -->
|
|
||||||
<!-- * * * * * * * * * * and can be replaced. * * * * * * * * * * * -->
|
|
||||||
<!-- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -->
|
|
||||||
<!-- * * * * * * * * * * End of Placeholder * * * * * * * * * * * * -->
|
|
||||||
<!-- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -->
|
|
||||||
|
|
||||||
|
|
||||||
<router-outlet></router-outlet>
|
|
@ -1,29 +0,0 @@
|
|||||||
import { TestBed } from '@angular/core/testing';
|
|
||||||
import { AppComponent } from './app.component';
|
|
||||||
|
|
||||||
describe('AppComponent', () => {
|
|
||||||
beforeEach(async () => {
|
|
||||||
await TestBed.configureTestingModule({
|
|
||||||
imports: [AppComponent],
|
|
||||||
}).compileComponents();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should create the app', () => {
|
|
||||||
const fixture = TestBed.createComponent(AppComponent);
|
|
||||||
const app = fixture.componentInstance;
|
|
||||||
expect(app).toBeTruthy();
|
|
||||||
});
|
|
||||||
|
|
||||||
it(`should have the 'angular-app' title`, () => {
|
|
||||||
const fixture = TestBed.createComponent(AppComponent);
|
|
||||||
const app = fixture.componentInstance;
|
|
||||||
expect(app.title).toEqual('angular-app');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should render title', () => {
|
|
||||||
const fixture = TestBed.createComponent(AppComponent);
|
|
||||||
fixture.detectChanges();
|
|
||||||
const compiled = fixture.nativeElement as HTMLElement;
|
|
||||||
expect(compiled.querySelector('h1')?.textContent).toContain('Hello, angular-app');
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,49 +0,0 @@
|
|||||||
import { Component } from '@angular/core';
|
|
||||||
import { CommonModule } from '@angular/common';
|
|
||||||
import { RouterOutlet } from '@angular/router';
|
|
||||||
import { FFmpeg } from '@ffmpeg/ffmpeg';
|
|
||||||
import { fetchFile, toBlobURL } from '@ffmpeg/util';
|
|
||||||
|
|
||||||
const baseURL = 'https://unpkg.com/@ffmpeg/core-mt@0.12.10/dist/esm';
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'app-root',
|
|
||||||
standalone: true,
|
|
||||||
imports: [CommonModule, RouterOutlet],
|
|
||||||
templateUrl: './app.component.html',
|
|
||||||
styleUrl: './app.component.css',
|
|
||||||
})
|
|
||||||
export class AppComponent {
|
|
||||||
loaded = false;
|
|
||||||
ffmpeg = new FFmpeg();
|
|
||||||
videoURL = '';
|
|
||||||
message = '';
|
|
||||||
async load() {
|
|
||||||
this.ffmpeg.on('log', ({ message }) => {
|
|
||||||
this.message = message;
|
|
||||||
});
|
|
||||||
await this.ffmpeg.load({
|
|
||||||
coreURL: await toBlobURL(`${baseURL}/ffmpeg-core.js`, 'text/javascript'),
|
|
||||||
wasmURL: await toBlobURL(
|
|
||||||
`${baseURL}/ffmpeg-core.wasm`,
|
|
||||||
'application/wasm',
|
|
||||||
),
|
|
||||||
workerURL: await toBlobURL(
|
|
||||||
`${baseURL}/ffmpeg-core.worker.js`,
|
|
||||||
'text/javascript',
|
|
||||||
),
|
|
||||||
});
|
|
||||||
this.loaded = true;
|
|
||||||
}
|
|
||||||
async transcode() {
|
|
||||||
const videoURL =
|
|
||||||
'https://raw.githubusercontent.com/ffmpegwasm/testdata/master/video-15s.avi';
|
|
||||||
await this.ffmpeg.writeFile('input.avi', await fetchFile(videoURL));
|
|
||||||
await this.ffmpeg.exec(['-i', 'input.avi', 'output.mp4']);
|
|
||||||
const fileData = await this.ffmpeg.readFile('output.mp4');
|
|
||||||
const data = new Uint8Array(fileData as ArrayBuffer);
|
|
||||||
this.videoURL = URL.createObjectURL(
|
|
||||||
new Blob([data.buffer], { type: 'video/mp4' }),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,8 +0,0 @@
|
|||||||
import { ApplicationConfig } from '@angular/core';
|
|
||||||
import { provideRouter } from '@angular/router';
|
|
||||||
|
|
||||||
import { routes } from './app.routes';
|
|
||||||
|
|
||||||
export const appConfig: ApplicationConfig = {
|
|
||||||
providers: [provideRouter(routes)]
|
|
||||||
};
|
|
@ -1,3 +0,0 @@
|
|||||||
import { Routes } from '@angular/router';
|
|
||||||
|
|
||||||
export const routes: Routes = [];
|
|
Before Width: | Height: | Size: 15 KiB |
@ -1,13 +0,0 @@
|
|||||||
<!doctype html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<title>AngularApp</title>
|
|
||||||
<base href="/">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
||||||
<link rel="icon" type="image/x-icon" href="favicon.ico">
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<app-root></app-root>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
@ -1,6 +0,0 @@
|
|||||||
import { bootstrapApplication } from '@angular/platform-browser';
|
|
||||||
import { appConfig } from './app/app.config';
|
|
||||||
import { AppComponent } from './app/app.component';
|
|
||||||
|
|
||||||
bootstrapApplication(AppComponent, appConfig)
|
|
||||||
.catch((err) => console.error(err));
|
|
@ -1 +0,0 @@
|
|||||||
/* You can add global styles to this file, and also import other style files */
|
|
@ -1,14 +0,0 @@
|
|||||||
/* To learn more about this file see: https://angular.io/config/tsconfig. */
|
|
||||||
{
|
|
||||||
"extends": "./tsconfig.json",
|
|
||||||
"compilerOptions": {
|
|
||||||
"outDir": "./out-tsc/app",
|
|
||||||
"types": []
|
|
||||||
},
|
|
||||||
"files": [
|
|
||||||
"src/main.ts"
|
|
||||||
],
|
|
||||||
"include": [
|
|
||||||
"src/**/*.d.ts"
|
|
||||||
]
|
|
||||||
}
|
|
@ -1,33 +0,0 @@
|
|||||||
/* To learn more about this file see: https://angular.io/config/tsconfig. */
|
|
||||||
{
|
|
||||||
"compileOnSave": false,
|
|
||||||
"compilerOptions": {
|
|
||||||
"outDir": "./dist/out-tsc",
|
|
||||||
"forceConsistentCasingInFileNames": true,
|
|
||||||
"strict": true,
|
|
||||||
"noImplicitOverride": true,
|
|
||||||
"noPropertyAccessFromIndexSignature": true,
|
|
||||||
"noImplicitReturns": true,
|
|
||||||
"noFallthroughCasesInSwitch": true,
|
|
||||||
"skipLibCheck": true,
|
|
||||||
"esModuleInterop": true,
|
|
||||||
"sourceMap": true,
|
|
||||||
"declaration": false,
|
|
||||||
"experimentalDecorators": true,
|
|
||||||
"moduleResolution": "node",
|
|
||||||
"importHelpers": true,
|
|
||||||
"target": "ES2022",
|
|
||||||
"module": "ES2022",
|
|
||||||
"useDefineForClassFields": false,
|
|
||||||
"lib": [
|
|
||||||
"ES2022",
|
|
||||||
"dom"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"angularCompilerOptions": {
|
|
||||||
"enableI18nLegacyMessageIdFormat": false,
|
|
||||||
"strictInjectionParameters": true,
|
|
||||||
"strictInputAccessModifiers": true,
|
|
||||||
"strictTemplates": true
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,14 +0,0 @@
|
|||||||
/* To learn more about this file see: https://angular.io/config/tsconfig. */
|
|
||||||
{
|
|
||||||
"extends": "./tsconfig.json",
|
|
||||||
"compilerOptions": {
|
|
||||||
"outDir": "./out-tsc/spec",
|
|
||||||
"types": [
|
|
||||||
"jasmine"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"include": [
|
|
||||||
"src/**/*.spec.ts",
|
|
||||||
"src/**/*.d.ts"
|
|
||||||
]
|
|
||||||
}
|
|
@ -1,3 +0,0 @@
|
|||||||
{
|
|
||||||
"extends": "next/core-web-vitals"
|
|
||||||
}
|
|
35
apps/nextjs-app/.gitignore
vendored
@ -1,35 +0,0 @@
|
|||||||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
|
||||||
|
|
||||||
# dependencies
|
|
||||||
/node_modules
|
|
||||||
/.pnp
|
|
||||||
.pnp.js
|
|
||||||
|
|
||||||
# testing
|
|
||||||
/coverage
|
|
||||||
|
|
||||||
# next.js
|
|
||||||
/.next/
|
|
||||||
/out/
|
|
||||||
|
|
||||||
# production
|
|
||||||
/build
|
|
||||||
|
|
||||||
# misc
|
|
||||||
.DS_Store
|
|
||||||
*.pem
|
|
||||||
|
|
||||||
# debug
|
|
||||||
npm-debug.log*
|
|
||||||
yarn-debug.log*
|
|
||||||
yarn-error.log*
|
|
||||||
|
|
||||||
# local env files
|
|
||||||
.env*.local
|
|
||||||
|
|
||||||
# vercel
|
|
||||||
.vercel
|
|
||||||
|
|
||||||
# typescript
|
|
||||||
*.tsbuildinfo
|
|
||||||
next-env.d.ts
|
|
@ -1,34 +0,0 @@
|
|||||||
This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app).
|
|
||||||
|
|
||||||
## Getting Started
|
|
||||||
|
|
||||||
First, run the development server:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
npm run dev
|
|
||||||
# or
|
|
||||||
yarn dev
|
|
||||||
# or
|
|
||||||
pnpm dev
|
|
||||||
```
|
|
||||||
|
|
||||||
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
|
|
||||||
|
|
||||||
You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file.
|
|
||||||
|
|
||||||
This project uses [`next/font`](https://nextjs.org/docs/basic-features/font-optimization) to automatically optimize and load Inter, a custom Google Font.
|
|
||||||
|
|
||||||
## Learn More
|
|
||||||
|
|
||||||
To learn more about Next.js, take a look at the following resources:
|
|
||||||
|
|
||||||
- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
|
|
||||||
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
|
|
||||||
|
|
||||||
You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome!
|
|
||||||
|
|
||||||
## Deploy on Vercel
|
|
||||||
|
|
||||||
The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
|
|
||||||
|
|
||||||
Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details.
|
|
@ -1,86 +0,0 @@
|
|||||||
"use client";
|
|
||||||
|
|
||||||
import { FFmpeg } from "@ffmpeg/ffmpeg";
|
|
||||||
import { fetchFile, toBlobURL } from "@ffmpeg/util";
|
|
||||||
import { useRef, useState } from "react";
|
|
||||||
|
|
||||||
export default function Home() {
|
|
||||||
const [loaded, setLoaded] = useState(false);
|
|
||||||
const [isLoading, setIsLoading] = useState(false);
|
|
||||||
const ffmpegRef = useRef(new FFmpeg());
|
|
||||||
const videoRef = useRef<HTMLVideoElement | null>(null);
|
|
||||||
const messageRef = useRef<HTMLParagraphElement | null>(null);
|
|
||||||
|
|
||||||
const load = async () => {
|
|
||||||
setIsLoading(true);
|
|
||||||
const baseURL = "https://unpkg.com/@ffmpeg/core@0.12.10/dist/umd";
|
|
||||||
const ffmpeg = ffmpegRef.current;
|
|
||||||
ffmpeg.on("log", ({ message }) => {
|
|
||||||
if (messageRef.current) messageRef.current.innerHTML = message;
|
|
||||||
});
|
|
||||||
// toBlobURL is used to bypass CORS issue, urls with the same
|
|
||||||
// domain can be used directly.
|
|
||||||
await ffmpeg.load({
|
|
||||||
coreURL: await toBlobURL(`${baseURL}/ffmpeg-core.js`, "text/javascript"),
|
|
||||||
wasmURL: await toBlobURL(
|
|
||||||
`${baseURL}/ffmpeg-core.wasm`,
|
|
||||||
"application/wasm"
|
|
||||||
),
|
|
||||||
});
|
|
||||||
setLoaded(true);
|
|
||||||
setIsLoading(false);
|
|
||||||
};
|
|
||||||
|
|
||||||
const transcode = async () => {
|
|
||||||
const ffmpeg = ffmpegRef.current;
|
|
||||||
// u can use 'https://ffmpegwasm.netlify.app/video/video-15s.avi' to download the video to public folder for testing
|
|
||||||
await ffmpeg.writeFile(
|
|
||||||
"input.avi",
|
|
||||||
await fetchFile(
|
|
||||||
"https://raw.githubusercontent.com/ffmpegwasm/testdata/master/video-15s.avi"
|
|
||||||
)
|
|
||||||
);
|
|
||||||
await ffmpeg.exec(["-i", "input.avi", "output.mp4"]);
|
|
||||||
const data = (await ffmpeg.readFile("output.mp4")) as any;
|
|
||||||
if (videoRef.current)
|
|
||||||
videoRef.current.src = URL.createObjectURL(
|
|
||||||
new Blob([data.buffer], { type: "video/mp4" })
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
return loaded ? (
|
|
||||||
<div className="fixed top-[50%] left-[50%] translate-x-[-50%] translate-y-[-50%]">
|
|
||||||
<video ref={videoRef} controls></video>
|
|
||||||
<br />
|
|
||||||
<button
|
|
||||||
onClick={transcode}
|
|
||||||
className="bg-green-500 hover:bg-green-700 text-white py-3 px-6 rounded"
|
|
||||||
>
|
|
||||||
Transcode avi to mp4
|
|
||||||
</button>
|
|
||||||
<p ref={messageRef}></p>
|
|
||||||
</div>
|
|
||||||
) : (
|
|
||||||
<button
|
|
||||||
className="fixed top-[50%] left-[50%] translate-x-[-50%] translate-y-[-50%] flex items-center bg-blue-500 hover:bg-blue-700 text-white py-2 px-4 rounded"
|
|
||||||
onClick={load}
|
|
||||||
>
|
|
||||||
Load ffmpeg-core
|
|
||||||
{isLoading && (
|
|
||||||
<span className="animate-spin ml-3">
|
|
||||||
<svg
|
|
||||||
viewBox="0 0 1024 1024"
|
|
||||||
focusable="false"
|
|
||||||
data-icon="loading"
|
|
||||||
width="1em"
|
|
||||||
height="1em"
|
|
||||||
fill="currentColor"
|
|
||||||
aria-hidden="true"
|
|
||||||
>
|
|
||||||
<path d="M988 548c-19.9 0-36-16.1-36-36 0-59.4-11.6-117-34.6-171.3a440.45 440.45 0 00-94.3-139.9 437.71 437.71 0 00-139.9-94.3C629 83.6 571.4 72 512 72c-19.9 0-36-16.1-36-36s16.1-36 36-36c69.1 0 136.2 13.5 199.3 40.3C772.3 66 827 103 874 150c47 47 83.9 101.8 109.7 162.7 26.7 63.1 40.2 130.2 40.2 199.3.1 19.9-16 36-35.9 36z"></path>
|
|
||||||
</svg>
|
|
||||||
</span>
|
|
||||||
)}
|
|
||||||
</button>
|
|
||||||
);
|
|
||||||
}
|
|
@ -1,8 +0,0 @@
|
|||||||
import dynamic from 'next/dynamic'
|
|
||||||
import React from 'react'
|
|
||||||
const NoSSRWrapper = props => (
|
|
||||||
<React.Fragment>{props.children}</React.Fragment>
|
|
||||||
)
|
|
||||||
export default dynamic(() => Promise.resolve(NoSSRWrapper), {
|
|
||||||
ssr: false
|
|
||||||
})
|
|
Before Width: | Height: | Size: 25 KiB |
@ -1,4 +0,0 @@
|
|||||||
@tailwind base;
|
|
||||||
@tailwind components;
|
|
||||||
@tailwind utilities;
|
|
||||||
|
|
@ -1,22 +0,0 @@
|
|||||||
import './globals.css'
|
|
||||||
import type { Metadata } from 'next'
|
|
||||||
import { Inter } from 'next/font/google'
|
|
||||||
|
|
||||||
const inter = Inter({ subsets: ['latin'] })
|
|
||||||
|
|
||||||
export const metadata: Metadata = {
|
|
||||||
title: 'Create Next App',
|
|
||||||
description: 'Generated by create next app',
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function RootLayout({
|
|
||||||
children,
|
|
||||||
}: {
|
|
||||||
children: React.ReactNode
|
|
||||||
}) {
|
|
||||||
return (
|
|
||||||
<html lang="en">
|
|
||||||
<body className={inter.className}>{children}</body>
|
|
||||||
</html>
|
|
||||||
)
|
|
||||||
}
|
|
@ -1,8 +0,0 @@
|
|||||||
'use client'
|
|
||||||
|
|
||||||
import NoSSRWrapper from "./NoSSRWrapper";
|
|
||||||
import Home from "./Home";
|
|
||||||
|
|
||||||
export default function Page() {
|
|
||||||
return <NoSSRWrapper><Home /></NoSSRWrapper>
|
|
||||||
}
|
|
@ -1,4 +0,0 @@
|
|||||||
/** @type {import('next').NextConfig} */
|
|
||||||
const nextConfig = {}
|
|
||||||
|
|
||||||
module.exports = nextConfig
|
|
@ -1,27 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "nextjs-ffmpeg-starter",
|
|
||||||
"version": "0.1.0",
|
|
||||||
"private": true,
|
|
||||||
"scripts": {
|
|
||||||
"dev": "next dev",
|
|
||||||
"build": "next build",
|
|
||||||
"start": "next start",
|
|
||||||
"lint": "next lint"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"@ffmpeg/ffmpeg": "*",
|
|
||||||
"@ffmpeg/util": "*",
|
|
||||||
"@types/node": "20.4.9",
|
|
||||||
"@types/react": "18.2.20",
|
|
||||||
"@types/react-dom": "18.2.7",
|
|
||||||
"autoprefixer": "10.4.14",
|
|
||||||
"eslint": "8.46.0",
|
|
||||||
"eslint-config-next": "13.4.13",
|
|
||||||
"next": "^14.0.4",
|
|
||||||
"postcss": "8.4.31",
|
|
||||||
"react": "18.2.0",
|
|
||||||
"react-dom": "18.2.0",
|
|
||||||
"tailwindcss": "3.3.3",
|
|
||||||
"typescript": "5.1.6"
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,6 +0,0 @@
|
|||||||
module.exports = {
|
|
||||||
plugins: {
|
|
||||||
tailwindcss: {},
|
|
||||||
autoprefixer: {},
|
|
||||||
},
|
|
||||||
}
|
|
@ -1 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 394 80"><path fill="#000" d="M262 0h68.5v12.7h-27.2v66.6h-13.6V12.7H262V0ZM149 0v12.7H94v20.4h44.3v12.6H94v21h55v12.6H80.5V0h68.7zm34.3 0h-17.8l63.8 79.4h17.9l-32-39.7 32-39.6h-17.9l-23 28.6-23-28.6zm18.3 56.7-9-11-27.1 33.7h17.8l18.3-22.7z"/><path fill="#000" d="M81 79.3 17 0H0v79.3h13.6V17l50.2 62.3H81Zm252.6-.4c-1 0-1.8-.4-2.5-1s-1.1-1.6-1.1-2.6.3-1.8 1-2.5 1.6-1 2.6-1 1.8.3 2.5 1a3.4 3.4 0 0 1 .6 4.3 3.7 3.7 0 0 1-3 1.8zm23.2-33.5h6v23.3c0 2.1-.4 4-1.3 5.5a9.1 9.1 0 0 1-3.8 3.5c-1.6.8-3.5 1.3-5.7 1.3-2 0-3.7-.4-5.3-1s-2.8-1.8-3.7-3.2c-.9-1.3-1.4-3-1.4-5h6c.1.8.3 1.6.7 2.2s1 1.2 1.6 1.5c.7.4 1.5.5 2.4.5 1 0 1.8-.2 2.4-.6a4 4 0 0 0 1.6-1.8c.3-.8.5-1.8.5-3V45.5zm30.9 9.1a4.4 4.4 0 0 0-2-3.3 7.5 7.5 0 0 0-4.3-1.1c-1.3 0-2.4.2-3.3.5-.9.4-1.6 1-2 1.6a3.5 3.5 0 0 0-.3 4c.3.5.7.9 1.3 1.2l1.8 1 2 .5 3.2.8c1.3.3 2.5.7 3.7 1.2a13 13 0 0 1 3.2 1.8 8.1 8.1 0 0 1 3 6.5c0 2-.5 3.7-1.5 5.1a10 10 0 0 1-4.4 3.5c-1.8.8-4.1 1.2-6.8 1.2-2.6 0-4.9-.4-6.8-1.2-2-.8-3.4-2-4.5-3.5a10 10 0 0 1-1.7-5.6h6a5 5 0 0 0 3.5 4.6c1 .4 2.2.6 3.4.6 1.3 0 2.5-.2 3.5-.6 1-.4 1.8-1 2.4-1.7a4 4 0 0 0 .8-2.4c0-.9-.2-1.6-.7-2.2a11 11 0 0 0-2.1-1.4l-3.2-1-3.8-1c-2.8-.7-5-1.7-6.6-3.2a7.2 7.2 0 0 1-2.4-5.7 8 8 0 0 1 1.7-5 10 10 0 0 1 4.3-3.5c2-.8 4-1.2 6.4-1.2 2.3 0 4.4.4 6.2 1.2 1.8.8 3.2 2 4.3 3.4 1 1.4 1.5 3 1.5 5h-5.8z"/></svg>
|
|
Before Width: | Height: | Size: 1.3 KiB |
@ -1 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 283 64"><path fill="black" d="M141 16c-11 0-19 7-19 18s9 18 20 18c7 0 13-3 16-7l-7-5c-2 3-6 4-9 4-5 0-9-3-10-7h28v-3c0-11-8-18-19-18zm-9 15c1-4 4-7 9-7s8 3 9 7h-18zm117-15c-11 0-19 7-19 18s9 18 20 18c6 0 12-3 16-7l-8-5c-2 3-5 4-8 4-5 0-9-3-11-7h28l1-3c0-11-8-18-19-18zm-10 15c2-4 5-7 10-7s8 3 9 7h-19zm-39 3c0 6 4 10 10 10 4 0 7-2 9-5l8 5c-3 5-9 8-17 8-11 0-19-7-19-18s8-18 19-18c8 0 14 3 17 8l-8 5c-2-3-5-5-9-5-6 0-10 4-10 10zm83-29v46h-9V5h9zM37 0l37 64H0L37 0zm92 5-27 48L74 5h10l18 30 17-30h10zm59 12v10l-3-1c-6 0-10 4-10 10v15h-9V17h9v9c0-5 6-9 13-9z"/></svg>
|
|
Before Width: | Height: | Size: 629 B |
@ -1,20 +0,0 @@
|
|||||||
import type { Config } from 'tailwindcss'
|
|
||||||
|
|
||||||
const config: Config = {
|
|
||||||
content: [
|
|
||||||
'./pages/**/*.{js,ts,jsx,tsx,mdx}',
|
|
||||||
'./components/**/*.{js,ts,jsx,tsx,mdx}',
|
|
||||||
'./app/**/*.{js,ts,jsx,tsx,mdx}',
|
|
||||||
],
|
|
||||||
theme: {
|
|
||||||
extend: {
|
|
||||||
backgroundImage: {
|
|
||||||
'gradient-radial': 'radial-gradient(var(--tw-gradient-stops))',
|
|
||||||
'gradient-conic':
|
|
||||||
'conic-gradient(from 180deg at 50% 50%, var(--tw-gradient-stops))',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
plugins: [],
|
|
||||||
}
|
|
||||||
export default config
|
|
@ -1,28 +0,0 @@
|
|||||||
{
|
|
||||||
"compilerOptions": {
|
|
||||||
"target": "es5",
|
|
||||||
"lib": ["dom", "dom.iterable", "esnext"],
|
|
||||||
"allowJs": true,
|
|
||||||
"skipLibCheck": true,
|
|
||||||
"strict": true,
|
|
||||||
"forceConsistentCasingInFileNames": true,
|
|
||||||
"noEmit": true,
|
|
||||||
"esModuleInterop": true,
|
|
||||||
"module": "esnext",
|
|
||||||
"moduleResolution": "bundler",
|
|
||||||
"resolveJsonModule": true,
|
|
||||||
"isolatedModules": true,
|
|
||||||
"jsx": "preserve",
|
|
||||||
"incremental": true,
|
|
||||||
"plugins": [
|
|
||||||
{
|
|
||||||
"name": "next"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"paths": {
|
|
||||||
"@/*": ["./*"]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
|
|
||||||
"exclude": ["node_modules"]
|
|
||||||
}
|
|
@ -1,18 +0,0 @@
|
|||||||
module.exports = {
|
|
||||||
root: true,
|
|
||||||
env: { browser: true, es2020: true },
|
|
||||||
extends: [
|
|
||||||
'eslint:recommended',
|
|
||||||
'plugin:@typescript-eslint/recommended',
|
|
||||||
'plugin:react-hooks/recommended',
|
|
||||||
],
|
|
||||||
ignorePatterns: ['dist', '.eslintrc.cjs'],
|
|
||||||
parser: '@typescript-eslint/parser',
|
|
||||||
plugins: ['react-refresh'],
|
|
||||||
rules: {
|
|
||||||
'react-refresh/only-export-components': [
|
|
||||||
'warn',
|
|
||||||
{ allowConstantExport: true },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
}
|
|
24
apps/react-vite-app/.gitignore
vendored
@ -1,24 +0,0 @@
|
|||||||
# Logs
|
|
||||||
logs
|
|
||||||
*.log
|
|
||||||
npm-debug.log*
|
|
||||||
yarn-debug.log*
|
|
||||||
yarn-error.log*
|
|
||||||
pnpm-debug.log*
|
|
||||||
lerna-debug.log*
|
|
||||||
|
|
||||||
node_modules
|
|
||||||
dist
|
|
||||||
dist-ssr
|
|
||||||
*.local
|
|
||||||
|
|
||||||
# Editor directories and files
|
|
||||||
.vscode/*
|
|
||||||
!.vscode/extensions.json
|
|
||||||
.idea
|
|
||||||
.DS_Store
|
|
||||||
*.suo
|
|
||||||
*.ntvs*
|
|
||||||
*.njsproj
|
|
||||||
*.sln
|
|
||||||
*.sw?
|
|
@ -1,27 +0,0 @@
|
|||||||
# React + TypeScript + Vite
|
|
||||||
|
|
||||||
This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.
|
|
||||||
|
|
||||||
Currently, two official plugins are available:
|
|
||||||
|
|
||||||
- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh
|
|
||||||
- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh
|
|
||||||
|
|
||||||
## Expanding the ESLint configuration
|
|
||||||
|
|
||||||
If you are developing a production application, we recommend updating the configuration to enable type aware lint rules:
|
|
||||||
|
|
||||||
- Configure the top-level `parserOptions` property like this:
|
|
||||||
|
|
||||||
```js
|
|
||||||
parserOptions: {
|
|
||||||
ecmaVersion: 'latest',
|
|
||||||
sourceType: 'module',
|
|
||||||
project: ['./tsconfig.json', './tsconfig.node.json'],
|
|
||||||
tsconfigRootDir: __dirname,
|
|
||||||
},
|
|
||||||
```
|
|
||||||
|
|
||||||
- Replace `plugin:@typescript-eslint/recommended` to `plugin:@typescript-eslint/recommended-type-checked` or `plugin:@typescript-eslint/strict-type-checked`
|
|
||||||
- Optionally add `plugin:@typescript-eslint/stylistic-type-checked`
|
|
||||||
- Install [eslint-plugin-react](https://github.com/jsx-eslint/eslint-plugin-react) and add `plugin:react/recommended` & `plugin:react/jsx-runtime` to the `extends` list
|
|
@ -1,13 +0,0 @@
|
|||||||
<!doctype html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8" />
|
|
||||||
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
||||||
<title>Vite + React + TS</title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div id="root"></div>
|
|
||||||
<script type="module" src="/src/main.tsx"></script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
@ -1,30 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "react-vite-app",
|
|
||||||
"private": true,
|
|
||||||
"version": "0.0.0",
|
|
||||||
"type": "module",
|
|
||||||
"scripts": {
|
|
||||||
"dev": "vite",
|
|
||||||
"build": "tsc && vite build",
|
|
||||||
"lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
|
|
||||||
"preview": "vite preview"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"@ffmpeg/ffmpeg": "*",
|
|
||||||
"@ffmpeg/util": "*",
|
|
||||||
"react": "^18.2.0",
|
|
||||||
"react-dom": "^18.2.0"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"@types/react": "^18.2.15",
|
|
||||||
"@types/react-dom": "^18.2.7",
|
|
||||||
"@typescript-eslint/eslint-plugin": "^6.0.0",
|
|
||||||
"@typescript-eslint/parser": "^6.0.0",
|
|
||||||
"@vitejs/plugin-react": "^4.0.3",
|
|
||||||
"eslint": "^8.45.0",
|
|
||||||
"eslint-plugin-react-hooks": "^4.6.0",
|
|
||||||
"eslint-plugin-react-refresh": "^0.4.3",
|
|
||||||
"typescript": "^5.0.2",
|
|
||||||
"vite": "^4.5.2"
|
|
||||||
}
|
|
||||||
}
|
|
@ -1 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>
|
|
Before Width: | Height: | Size: 1.5 KiB |
@ -1,60 +0,0 @@
|
|||||||
import { useState, useRef } from "react";
|
|
||||||
import { FFmpeg } from "@ffmpeg/ffmpeg";
|
|
||||||
import { toBlobURL, fetchFile } from "@ffmpeg/util";
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
const [loaded, setLoaded] = useState(false);
|
|
||||||
const ffmpegRef = useRef(new FFmpeg());
|
|
||||||
const videoRef = useRef<HTMLVideoElement | null>(null);
|
|
||||||
const messageRef = useRef<HTMLParagraphElement | null>(null);
|
|
||||||
|
|
||||||
const load = async () => {
|
|
||||||
const baseURL = "https://unpkg.com/@ffmpeg/core-mt@0.12.10/dist/esm";
|
|
||||||
const ffmpeg = ffmpegRef.current;
|
|
||||||
ffmpeg.on("log", ({ message }) => {
|
|
||||||
if (messageRef.current) messageRef.current.innerHTML = message;
|
|
||||||
});
|
|
||||||
// toBlobURL is used to bypass CORS issue, urls with the same
|
|
||||||
// domain can be used directly.
|
|
||||||
await ffmpeg.load({
|
|
||||||
coreURL: await toBlobURL(`${baseURL}/ffmpeg-core.js`, "text/javascript"),
|
|
||||||
wasmURL: await toBlobURL(
|
|
||||||
`${baseURL}/ffmpeg-core.wasm`,
|
|
||||||
"application/wasm"
|
|
||||||
),
|
|
||||||
workerURL: await toBlobURL(
|
|
||||||
`${baseURL}/ffmpeg-core.worker.js`,
|
|
||||||
"text/javascript"
|
|
||||||
),
|
|
||||||
});
|
|
||||||
setLoaded(true);
|
|
||||||
};
|
|
||||||
|
|
||||||
const transcode = async () => {
|
|
||||||
const videoURL =
|
|
||||||
"https://raw.githubusercontent.com/ffmpegwasm/testdata/master/video-15s.avi";
|
|
||||||
const ffmpeg = ffmpegRef.current;
|
|
||||||
await ffmpeg.writeFile("input.avi", await fetchFile(videoURL));
|
|
||||||
await ffmpeg.exec(["-i", "input.avi", "output.mp4"]);
|
|
||||||
const fileData = await ffmpeg.readFile("output.mp4");
|
|
||||||
const data = new Uint8Array(fileData as ArrayBuffer);
|
|
||||||
if (videoRef.current) {
|
|
||||||
videoRef.current.src = URL.createObjectURL(
|
|
||||||
new Blob([data.buffer], { type: "video/mp4" })
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return loaded ? (
|
|
||||||
<>
|
|
||||||
<video ref={videoRef} controls></video>
|
|
||||||
<br />
|
|
||||||
<button onClick={transcode}>Transcode avi to mp4</button>
|
|
||||||
<p ref={messageRef}></p>
|
|
||||||
</>
|
|
||||||
) : (
|
|
||||||
<button onClick={load}>Load ffmpeg-core</button>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default App;
|
|
@ -1,70 +0,0 @@
|
|||||||
:root {
|
|
||||||
font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
|
|
||||||
line-height: 1.5;
|
|
||||||
font-weight: 400;
|
|
||||||
|
|
||||||
color-scheme: light dark;
|
|
||||||
color: rgba(255, 255, 255, 0.87);
|
|
||||||
background-color: #242424;
|
|
||||||
|
|
||||||
font-synthesis: none;
|
|
||||||
text-rendering: optimizeLegibility;
|
|
||||||
-webkit-font-smoothing: antialiased;
|
|
||||||
-moz-osx-font-smoothing: grayscale;
|
|
||||||
-webkit-text-size-adjust: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
a {
|
|
||||||
font-weight: 500;
|
|
||||||
color: #646cff;
|
|
||||||
text-decoration: inherit;
|
|
||||||
}
|
|
||||||
a:hover {
|
|
||||||
color: #535bf2;
|
|
||||||
}
|
|
||||||
|
|
||||||
body {
|
|
||||||
margin: 0;
|
|
||||||
display: flex;
|
|
||||||
place-items: center;
|
|
||||||
min-width: 320px;
|
|
||||||
min-height: 100vh;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
h1 {
|
|
||||||
font-size: 3.2em;
|
|
||||||
line-height: 1.1;
|
|
||||||
}
|
|
||||||
|
|
||||||
button {
|
|
||||||
border-radius: 8px;
|
|
||||||
border: 1px solid transparent;
|
|
||||||
padding: 0.6em 1.2em;
|
|
||||||
font-size: 1em;
|
|
||||||
font-weight: 500;
|
|
||||||
font-family: inherit;
|
|
||||||
background-color: #1a1a1a;
|
|
||||||
cursor: pointer;
|
|
||||||
transition: border-color 0.25s;
|
|
||||||
}
|
|
||||||
button:hover {
|
|
||||||
border-color: #646cff;
|
|
||||||
}
|
|
||||||
button:focus,
|
|
||||||
button:focus-visible {
|
|
||||||
outline: 4px auto -webkit-focus-ring-color;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (prefers-color-scheme: light) {
|
|
||||||
:root {
|
|
||||||
color: #213547;
|
|
||||||
background-color: #ffffff;
|
|
||||||
}
|
|
||||||
a:hover {
|
|
||||||
color: #747bff;
|
|
||||||
}
|
|
||||||
button {
|
|
||||||
background-color: #f9f9f9;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,10 +0,0 @@
|
|||||||
import React from 'react'
|
|
||||||
import ReactDOM from 'react-dom/client'
|
|
||||||
import App from './App.tsx'
|
|
||||||
import './index.css'
|
|
||||||
|
|
||||||
ReactDOM.createRoot(document.getElementById('root')!).render(
|
|
||||||
<React.StrictMode>
|
|
||||||
<App />
|
|
||||||
</React.StrictMode>,
|
|
||||||
)
|
|
1
apps/react-vite-app/src/vite-env.d.ts
vendored
@ -1 +0,0 @@
|
|||||||
/// <reference types="vite/client" />
|
|
@ -1,25 +0,0 @@
|
|||||||
{
|
|
||||||
"compilerOptions": {
|
|
||||||
"target": "ES2020",
|
|
||||||
"useDefineForClassFields": true,
|
|
||||||
"lib": ["ES2020", "DOM", "DOM.Iterable"],
|
|
||||||
"module": "ESNext",
|
|
||||||
"skipLibCheck": true,
|
|
||||||
|
|
||||||
/* Bundler mode */
|
|
||||||
"moduleResolution": "bundler",
|
|
||||||
"allowImportingTsExtensions": true,
|
|
||||||
"resolveJsonModule": true,
|
|
||||||
"isolatedModules": true,
|
|
||||||
"noEmit": true,
|
|
||||||
"jsx": "react-jsx",
|
|
||||||
|
|
||||||
/* Linting */
|
|
||||||
"strict": true,
|
|
||||||
"noUnusedLocals": true,
|
|
||||||
"noUnusedParameters": true,
|
|
||||||
"noFallthroughCasesInSwitch": true
|
|
||||||
},
|
|
||||||
"include": ["src"],
|
|
||||||
"references": [{ "path": "./tsconfig.node.json" }]
|
|
||||||
}
|
|
@ -1,10 +0,0 @@
|
|||||||
{
|
|
||||||
"compilerOptions": {
|
|
||||||
"composite": true,
|
|
||||||
"skipLibCheck": true,
|
|
||||||
"module": "ESNext",
|
|
||||||
"moduleResolution": "bundler",
|
|
||||||
"allowSyntheticDefaultImports": true
|
|
||||||
},
|
|
||||||
"include": ["vite.config.ts"]
|
|
||||||
}
|
|
@ -1,16 +0,0 @@
|
|||||||
import { defineConfig } from "vite";
|
|
||||||
import react from "@vitejs/plugin-react";
|
|
||||||
|
|
||||||
// https://vitejs.dev/config/
|
|
||||||
export default defineConfig({
|
|
||||||
plugins: [react()],
|
|
||||||
optimizeDeps: {
|
|
||||||
exclude: ["@ffmpeg/ffmpeg", "@ffmpeg/util"],
|
|
||||||
},
|
|
||||||
server: {
|
|
||||||
headers: {
|
|
||||||
"Cross-Origin-Opener-Policy": "same-origin",
|
|
||||||
"Cross-Origin-Embedder-Policy": "require-corp",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
28
apps/solidstart-app/.gitignore
vendored
@ -1,28 +0,0 @@
|
|||||||
|
|
||||||
dist
|
|
||||||
.solid
|
|
||||||
.output
|
|
||||||
.vercel
|
|
||||||
.netlify
|
|
||||||
.vinxi
|
|
||||||
|
|
||||||
# Environment
|
|
||||||
.env
|
|
||||||
.env*.local
|
|
||||||
|
|
||||||
# dependencies
|
|
||||||
/node_modules
|
|
||||||
|
|
||||||
# IDEs and editors
|
|
||||||
/.idea
|
|
||||||
.project
|
|
||||||
.classpath
|
|
||||||
*.launch
|
|
||||||
.settings/
|
|
||||||
|
|
||||||
# Temp
|
|
||||||
gitignore
|
|
||||||
|
|
||||||
# System Files
|
|
||||||
.DS_Store
|
|
||||||
Thumbs.db
|
|
@ -1,32 +0,0 @@
|
|||||||
# SolidStart
|
|
||||||
|
|
||||||
Everything you need to build a Solid project, powered by [`solid-start`](https://start.solidjs.com);
|
|
||||||
|
|
||||||
## Creating a project
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# create a new project in the current directory
|
|
||||||
npm init solid@latest
|
|
||||||
|
|
||||||
# create a new project in my-app
|
|
||||||
npm init solid@latest my-app
|
|
||||||
```
|
|
||||||
|
|
||||||
## Developing
|
|
||||||
|
|
||||||
Once you've created a project and installed dependencies with `npm install` (or `pnpm install` or `yarn`), start a development server:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
npm run dev
|
|
||||||
|
|
||||||
# or start the server and open the app in a new browser tab
|
|
||||||
npm run dev -- --open
|
|
||||||
```
|
|
||||||
|
|
||||||
## Building
|
|
||||||
|
|
||||||
Solid apps are built with _presets_, which optimise your project for deployment to different environments.
|
|
||||||
|
|
||||||
By default, `npm run build` will generate a Node app that you can run with `npm start`. To use a different preset, add it to the `devDependencies` in `package.json` and specify in your `app.config.js`.
|
|
||||||
|
|
||||||
## This project was created with the [Solid CLI](https://solid-cli.netlify.app)
|
|
@ -1,13 +0,0 @@
|
|||||||
import { defineConfig } from "@solidjs/start/config";
|
|
||||||
|
|
||||||
export default defineConfig({
|
|
||||||
ssr: false,
|
|
||||||
server: {
|
|
||||||
static: true,
|
|
||||||
},
|
|
||||||
vite: {
|
|
||||||
optimizeDeps: {
|
|
||||||
exclude: ['@ffmpeg/ffmpeg', '@ffmpeg/util']
|
|
||||||
},
|
|
||||||
}
|
|
||||||
});
|
|
8251
apps/solidstart-app/package-lock.json
generated
@ -1,23 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "solidstart-ffmpeg",
|
|
||||||
"type": "module",
|
|
||||||
"scripts": {
|
|
||||||
"dev": "vinxi dev",
|
|
||||||
"build": "vinxi build",
|
|
||||||
"start": "vinxi start"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"@ffmpeg/ffmpeg": "^0.12.15",
|
|
||||||
"@ffmpeg/util": "^0.12.2",
|
|
||||||
"@solidjs/router": "^0.14.1",
|
|
||||||
"@solidjs/start": "^1.0.4",
|
|
||||||
"autoprefixer": "^10.4.19",
|
|
||||||
"postcss": "^8.4.38",
|
|
||||||
"solid-js": "^1.8.18",
|
|
||||||
"tailwindcss": "^3.4.3",
|
|
||||||
"vinxi": "^0.3.14"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=18"
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,6 +0,0 @@
|
|||||||
module.exports = {
|
|
||||||
plugins: {
|
|
||||||
tailwindcss: {},
|
|
||||||
autoprefixer: {},
|
|
||||||
},
|
|
||||||
}
|
|
Before Width: | Height: | Size: 664 B |
@ -1,20 +0,0 @@
|
|||||||
@tailwind base;
|
|
||||||
@tailwind components;
|
|
||||||
@tailwind utilities;
|
|
||||||
|
|
||||||
:root {
|
|
||||||
--background-rgb: 214, 219, 220;
|
|
||||||
--foreground-rgb: 0, 0, 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (prefers-color-scheme: dark) {
|
|
||||||
:root {
|
|
||||||
--background-rgb: 0, 0, 0;
|
|
||||||
--foreground-rgb: 255, 255, 255;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
body {
|
|
||||||
background: rgb(var(--background-rgb));
|
|
||||||
color: rgb(var(--foreground-rgb));
|
|
||||||
}
|
|
@ -1,17 +0,0 @@
|
|||||||
import { Router } from '@solidjs/router';
|
|
||||||
import { FileRoutes } from '@solidjs/start/router';
|
|
||||||
import { Suspense } from 'solid-js';
|
|
||||||
import './app.css';
|
|
||||||
|
|
||||||
export default function App() {
|
|
||||||
return (
|
|
||||||
<Router
|
|
||||||
root={(props) => (
|
|
||||||
<>
|
|
||||||
<Suspense>{props.children}</Suspense>
|
|
||||||
</>
|
|
||||||
)}>
|
|
||||||
<FileRoutes />
|
|
||||||
</Router>
|
|
||||||
);
|
|
||||||
}
|
|
@ -1,4 +0,0 @@
|
|||||||
// @refresh reload
|
|
||||||
import { mount, StartClient } from "@solidjs/start/client";
|
|
||||||
|
|
||||||
mount(() => <StartClient />, document.getElementById("app")!);
|
|
@ -1,25 +0,0 @@
|
|||||||
// @refresh reload
|
|
||||||
import { createHandler, StartServer } from '@solidjs/start/server';
|
|
||||||
import { HttpHeader, HttpStatusCode } from '@solidjs/start';
|
|
||||||
|
|
||||||
export default createHandler(() => (
|
|
||||||
<StartServer
|
|
||||||
document={({ assets, children, scripts }) => (
|
|
||||||
<html lang='en'>
|
|
||||||
{/*necessary because ffmpeg library uses sharedArrayBuffer */}
|
|
||||||
<HttpHeader name='Cross-Origin-Opener-Policy' value='same-origin' />
|
|
||||||
<HttpHeader name='Cross-Origin-Embedder-Policy' value='require-corp' />
|
|
||||||
<head>
|
|
||||||
<meta charset='utf-8' />
|
|
||||||
<meta name='viewport' content='width=device-width, initial-scale=1' />
|
|
||||||
<link rel='icon' href='/favicon.ico' />
|
|
||||||
{assets}
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div id='app'>{children}</div>
|
|
||||||
{scripts}
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
));
|
|
1
apps/solidstart-app/src/global.d.ts
vendored
@ -1 +0,0 @@
|
|||||||
/// <reference types="@solidjs/start/env" />
|
|
@ -1,87 +0,0 @@
|
|||||||
import { FFmpeg } from '@ffmpeg/ffmpeg';
|
|
||||||
import { fetchFile, toBlobURL } from '@ffmpeg/util';
|
|
||||||
import { createSignal, Show } from 'solid-js';
|
|
||||||
|
|
||||||
const baseURL = 'https://unpkg.com/@ffmpeg/core-mt@0.12.6/dist/esm';
|
|
||||||
const videoURL =
|
|
||||||
'https://raw.githubusercontent.com/ffmpegwasm/testdata/master/video-15s.avi';
|
|
||||||
|
|
||||||
export default function Home() {
|
|
||||||
const [loaded, setLoaded] = createSignal(false);
|
|
||||||
const [isLoading, setIsLoading] = createSignal(false);
|
|
||||||
let ffmpegRef = new FFmpeg();
|
|
||||||
let videoRef: any = null;
|
|
||||||
let messageRef: any = null;
|
|
||||||
|
|
||||||
const load = async () => {
|
|
||||||
setIsLoading(true);
|
|
||||||
const ffmpeg = ffmpegRef;
|
|
||||||
ffmpeg.on('log', ({ message }) => {
|
|
||||||
if (messageRef) messageRef.innerHTML = message;
|
|
||||||
});
|
|
||||||
// toBlobURL is used to bypass CORS issue, urls with the same
|
|
||||||
// domain can be used directly.
|
|
||||||
|
|
||||||
await ffmpeg.load({
|
|
||||||
coreURL: await toBlobURL(`${baseURL}/ffmpeg-core.js`, 'text/javascript'),
|
|
||||||
wasmURL: await toBlobURL(
|
|
||||||
`${baseURL}/ffmpeg-core.wasm`,
|
|
||||||
'application/wasm'
|
|
||||||
),
|
|
||||||
workerURL: await toBlobURL(
|
|
||||||
`${baseURL}/ffmpeg-core.worker.js`,
|
|
||||||
'text/javascript'
|
|
||||||
),
|
|
||||||
});
|
|
||||||
setLoaded(true);
|
|
||||||
setIsLoading(false);
|
|
||||||
};
|
|
||||||
|
|
||||||
const transcode = async () => {
|
|
||||||
const ffmpeg = ffmpegRef;
|
|
||||||
// u can use 'https://ffmpegwasm.netlify.app/video/video-15s.avi' to download the video to public folder for testing
|
|
||||||
await ffmpeg.writeFile('input.avi', await fetchFile(videoURL));
|
|
||||||
await ffmpeg.exec(['-i', 'input.avi', 'output.mp4']);
|
|
||||||
const data = (await ffmpeg.readFile('output.mp4')) as any;
|
|
||||||
if (videoRef)
|
|
||||||
videoRef.src = URL.createObjectURL(
|
|
||||||
new Blob([data.buffer], { type: 'video/mp4' })
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Show
|
|
||||||
when={loaded()}
|
|
||||||
fallback={
|
|
||||||
<button
|
|
||||||
class='fixed top-[50%] left-[50%] translate-x-[-50%] translate-y-[-50%] flex items-center bg-blue-500 hover:bg-blue-700 text-white py-2 px-4 rounded'
|
|
||||||
onClick={load}>
|
|
||||||
Load ffmpeg-core
|
|
||||||
<Show when={isLoading()}>
|
|
||||||
<span class='animate-spin ml-3'>
|
|
||||||
<svg
|
|
||||||
viewBox='0 0 1024 1024'
|
|
||||||
data-icon='loading'
|
|
||||||
width='1em'
|
|
||||||
height='1em'
|
|
||||||
fill='currentColor'
|
|
||||||
aria-hidden='true'>
|
|
||||||
<path d='M988 548c-19.9 0-36-16.1-36-36 0-59.4-11.6-117-34.6-171.3a440.45 440.45 0 00-94.3-139.9 437.71 437.71 0 00-139.9-94.3C629 83.6 571.4 72 512 72c-19.9 0-36-16.1-36-36s16.1-36 36-36c69.1 0 136.2 13.5 199.3 40.3C772.3 66 827 103 874 150c47 47 83.9 101.8 109.7 162.7 26.7 63.1 40.2 130.2 40.2 199.3.1 19.9-16 36-35.9 36z'></path>
|
|
||||||
</svg>
|
|
||||||
</span>
|
|
||||||
</Show>
|
|
||||||
</button>
|
|
||||||
}>
|
|
||||||
<div class='fixed top-[50%] left-[50%] translate-x-[-50%] translate-y-[-50%]'>
|
|
||||||
<video ref={videoRef} controls></video>
|
|
||||||
<br />
|
|
||||||
<button
|
|
||||||
onClick={transcode}
|
|
||||||
class='bg-green-500 hover:bg-green-700 text-white py-3 px-6 rounded'>
|
|
||||||
Transcode avi to mp4
|
|
||||||
</button>
|
|
||||||
<p ref={messageRef}></p>
|
|
||||||
</div>
|
|
||||||
</Show>
|
|
||||||
);
|
|
||||||
}
|
|
@ -1,8 +0,0 @@
|
|||||||
/** @type {import('tailwindcss').Config} */
|
|
||||||
module.exports = {
|
|
||||||
content: ["./src/**/*.{html,js,jsx,ts,tsx}"],
|
|
||||||
theme: {
|
|
||||||
extend: {}
|
|
||||||
},
|
|
||||||
plugins: []
|
|
||||||
};
|
|
@ -1,19 +0,0 @@
|
|||||||
{
|
|
||||||
"compilerOptions": {
|
|
||||||
"target": "ESNext",
|
|
||||||
"module": "ESNext",
|
|
||||||
"moduleResolution": "bundler",
|
|
||||||
"allowSyntheticDefaultImports": true,
|
|
||||||
"esModuleInterop": true,
|
|
||||||
"jsx": "preserve",
|
|
||||||
"jsxImportSource": "solid-js",
|
|
||||||
"allowJs": true,
|
|
||||||
"noEmit": true,
|
|
||||||
"strict": true,
|
|
||||||
"types": ["vinxi/types/client"],
|
|
||||||
"isolatedModules": true,
|
|
||||||
"paths": {
|
|
||||||
"~/*": ["./src/*"]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,13 +0,0 @@
|
|||||||
.DS_Store
|
|
||||||
node_modules
|
|
||||||
/build
|
|
||||||
/.svelte-kit
|
|
||||||
/package
|
|
||||||
.env
|
|
||||||
.env.*
|
|
||||||
!.env.example
|
|
||||||
|
|
||||||
# Ignore files for PNPM, NPM and YARN
|
|
||||||
pnpm-lock.yaml
|
|
||||||
package-lock.json
|
|
||||||
yarn.lock
|
|
@ -1,31 +0,0 @@
|
|||||||
/** @type { import("eslint").Linter.Config } */
|
|
||||||
module.exports = {
|
|
||||||
root: true,
|
|
||||||
extends: [
|
|
||||||
'eslint:recommended',
|
|
||||||
'plugin:@typescript-eslint/recommended',
|
|
||||||
'plugin:svelte/recommended',
|
|
||||||
'prettier'
|
|
||||||
],
|
|
||||||
parser: '@typescript-eslint/parser',
|
|
||||||
plugins: ['@typescript-eslint'],
|
|
||||||
parserOptions: {
|
|
||||||
sourceType: 'module',
|
|
||||||
ecmaVersion: 2020,
|
|
||||||
extraFileExtensions: ['.svelte']
|
|
||||||
},
|
|
||||||
env: {
|
|
||||||
browser: true,
|
|
||||||
es2017: true,
|
|
||||||
node: true
|
|
||||||
},
|
|
||||||
overrides: [
|
|
||||||
{
|
|
||||||
files: ['*.svelte'],
|
|
||||||
parser: 'svelte-eslint-parser',
|
|
||||||
parserOptions: {
|
|
||||||
parser: '@typescript-eslint/parser'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
};
|
|
10
apps/sveltekit-app/.gitignore
vendored
@ -1,10 +0,0 @@
|
|||||||
.DS_Store
|
|
||||||
node_modules
|
|
||||||
/build
|
|
||||||
/.svelte-kit
|
|
||||||
/package
|
|
||||||
.env
|
|
||||||
.env.*
|
|
||||||
!.env.example
|
|
||||||
vite.config.js.timestamp-*
|
|
||||||
vite.config.ts.timestamp-*
|
|
@ -1 +0,0 @@
|
|||||||
engine-strict=true
|
|
@ -1,4 +0,0 @@
|
|||||||
# Ignore files for PNPM, NPM and YARN
|
|
||||||
pnpm-lock.yaml
|
|
||||||
package-lock.json
|
|
||||||
yarn.lock
|
|
@ -1,8 +0,0 @@
|
|||||||
{
|
|
||||||
"useTabs": true,
|
|
||||||
"singleQuote": true,
|
|
||||||
"trailingComma": "none",
|
|
||||||
"printWidth": 100,
|
|
||||||
"plugins": ["prettier-plugin-svelte"],
|
|
||||||
"overrides": [{ "files": "*.svelte", "options": { "parser": "svelte" } }]
|
|
||||||
}
|
|
@ -1,38 +0,0 @@
|
|||||||
# create-svelte
|
|
||||||
|
|
||||||
Everything you need to build a Svelte project, powered by [`create-svelte`](https://github.com/sveltejs/kit/tree/main/packages/create-svelte).
|
|
||||||
|
|
||||||
## Creating a project
|
|
||||||
|
|
||||||
If you're seeing this, you've probably already done this step. Congrats!
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# create a new project in the current directory
|
|
||||||
npm create svelte@latest
|
|
||||||
|
|
||||||
# create a new project in my-app
|
|
||||||
npm create svelte@latest my-app
|
|
||||||
```
|
|
||||||
|
|
||||||
## Developing
|
|
||||||
|
|
||||||
Once you've created a project and installed dependencies with `npm install` (or `pnpm install` or `yarn`), start a development server:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
npm run dev
|
|
||||||
|
|
||||||
# or start the server and open the app in a new browser tab
|
|
||||||
npm run dev -- --open
|
|
||||||
```
|
|
||||||
|
|
||||||
## Building
|
|
||||||
|
|
||||||
To create a production version of your app:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
npm run build
|
|
||||||
```
|
|
||||||
|
|
||||||
You can preview the production build with `npm run preview`.
|
|
||||||
|
|
||||||
> To deploy your app, you may need to install an [adapter](https://kit.svelte.dev/docs/adapters) for your target environment.
|
|
@ -1,41 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "sveltekit-app",
|
|
||||||
"version": "0.0.1",
|
|
||||||
"private": true,
|
|
||||||
"scripts": {
|
|
||||||
"dev": "vite dev",
|
|
||||||
"build": "vite build",
|
|
||||||
"preview": "vite preview",
|
|
||||||
"test": "npm run test:integration && npm run test:unit",
|
|
||||||
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
|
|
||||||
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
|
|
||||||
"lint": "prettier --check . && eslint .",
|
|
||||||
"format": "prettier --write .",
|
|
||||||
"test:integration": "playwright test",
|
|
||||||
"test:unit": "vitest"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"@ffmpeg/ffmpeg": "*",
|
|
||||||
"@ffmpeg/util": "*",
|
|
||||||
"@playwright/test": "^1.41.2",
|
|
||||||
"@sveltejs/adapter-auto": "^3.1.1",
|
|
||||||
"@sveltejs/kit": "^2.5.0",
|
|
||||||
"@sveltejs/vite-plugin-svelte": "^3.0.2",
|
|
||||||
"@tsconfig/node18": "^18.2.2",
|
|
||||||
"@types/eslint": "8.56.2",
|
|
||||||
"@typescript-eslint/eslint-plugin": "^6.21.0",
|
|
||||||
"@typescript-eslint/parser": "^6.21.0",
|
|
||||||
"eslint": "^8.56.0",
|
|
||||||
"eslint-config-prettier": "^9.1.0",
|
|
||||||
"eslint-plugin-svelte": "^2.35.1",
|
|
||||||
"prettier": "^3.2.5",
|
|
||||||
"prettier-plugin-svelte": "^3.1.2",
|
|
||||||
"svelte": "^4.2.10",
|
|
||||||
"svelte-check": "^3.6.4",
|
|
||||||
"tslib": "^2.6.2",
|
|
||||||
"typescript": "^5.3.3",
|
|
||||||
"vite": "^5.1.1",
|
|
||||||
"vitest": "^1.2.2"
|
|
||||||
},
|
|
||||||
"type": "module"
|
|
||||||
}
|
|
@ -1,12 +0,0 @@
|
|||||||
import type { PlaywrightTestConfig } from '@playwright/test';
|
|
||||||
|
|
||||||
const config: PlaywrightTestConfig = {
|
|
||||||
webServer: {
|
|
||||||
command: 'npm run build && npm run preview',
|
|
||||||
port: 4173
|
|
||||||
},
|
|
||||||
testDir: 'tests',
|
|
||||||
testMatch: /(.+\.)?(test|spec)\.[jt]s/
|
|
||||||
};
|
|
||||||
|
|
||||||
export default config;
|
|
13
apps/sveltekit-app/src/app.d.ts
vendored
@ -1,13 +0,0 @@
|
|||||||
// See https://kit.svelte.dev/docs/types#app
|
|
||||||
// for information about these interfaces
|
|
||||||
declare global {
|
|
||||||
namespace App {
|
|
||||||
// interface Error {}
|
|
||||||
// interface Locals {}
|
|
||||||
// interface PageData {}
|
|
||||||
// interface PageState {}
|
|
||||||
// interface Platform {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export {};
|
|
@ -1,12 +0,0 @@
|
|||||||
<!doctype html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8" />
|
|
||||||
<link rel="icon" href="%sveltekit.assets%/favicon.png" />
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
||||||
%sveltekit.head%
|
|
||||||
</head>
|
|
||||||
<body data-sveltekit-preload-data="hover">
|
|
||||||
<div style="display: contents">%sveltekit.body%</div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
@ -1,7 +0,0 @@
|
|||||||
import { describe, it, expect } from 'vitest';
|
|
||||||
|
|
||||||
describe('sum test', () => {
|
|
||||||
it('adds 1 + 2 to equal 3', () => {
|
|
||||||
expect(1 + 2).toBe(3);
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,44 +0,0 @@
|
|||||||
<script lang="ts">
|
|
||||||
import { FFmpeg } from '@ffmpeg/ffmpeg';
|
|
||||||
// @ts-ignore
|
|
||||||
import type { LogEvent } from '@ffmpeg/ffmpeg/dist/esm/types';
|
|
||||||
import { fetchFile, toBlobURL } from '@ffmpeg/util';
|
|
||||||
|
|
||||||
let videoEl: HTMLVideoElement;
|
|
||||||
|
|
||||||
const baseURL = 'https://unpkg.com/@ffmpeg/core-mt@0.12.6/dist/esm';
|
|
||||||
const videoURL = 'https://raw.githubusercontent.com/ffmpegwasm/testdata/master/video-15s.avi';
|
|
||||||
|
|
||||||
let message = 'Click Start to Transcode';
|
|
||||||
|
|
||||||
async function transcode() {
|
|
||||||
const ffmpeg = new FFmpeg();
|
|
||||||
message = 'Loading ffmpeg-core.js';
|
|
||||||
ffmpeg.on('log', ({ message: msg }: LogEvent) => {
|
|
||||||
message = msg;
|
|
||||||
console.log(message);
|
|
||||||
});
|
|
||||||
await ffmpeg.load({
|
|
||||||
coreURL: await toBlobURL(`${baseURL}/ffmpeg-core.js`, 'text/javascript'),
|
|
||||||
wasmURL: await toBlobURL(`${baseURL}/ffmpeg-core.wasm`, 'application/wasm'),
|
|
||||||
workerURL: await toBlobURL(`${baseURL}/ffmpeg-core.worker.js`, 'text/javascript')
|
|
||||||
});
|
|
||||||
message = 'Start transcoding';
|
|
||||||
await ffmpeg.writeFile('test.avi', await fetchFile(videoURL));
|
|
||||||
await ffmpeg.exec(['-i', 'test.avi', 'test.mp4']);
|
|
||||||
message = 'Complete transcoding';
|
|
||||||
const data = await ffmpeg.readFile('test.mp4');
|
|
||||||
console.log('done');
|
|
||||||
videoEl.src = URL.createObjectURL(
|
|
||||||
new Blob([(data as Uint8Array).buffer], { type: 'video/mp4' })
|
|
||||||
);
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<!-- svelte-ignore a11y-media-has-caption -->
|
|
||||||
<video bind:this={videoEl} controls />
|
|
||||||
<br />
|
|
||||||
<button on:click={transcode}>Start</button>
|
|
||||||
<p>{message}</p>
|
|
||||||
</div>
|
|
@ -1 +0,0 @@
|
|||||||
// place files you want to import through the `$lib` alias in this folder.
|
|
@ -1,7 +0,0 @@
|
|||||||
<script lang="ts">
|
|
||||||
import FFmpegDemo from '../lib/FFmpegDemo.svelte';
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<h1>Welcome to SvelteKit</h1>
|
|
||||||
<p>Visit <a href="https://kit.svelte.dev">kit.svelte.dev</a> to read the documentation</p>
|
|
||||||
<FFmpegDemo></FFmpegDemo>
|
|
Before Width: | Height: | Size: 1.5 KiB |
@ -1,18 +0,0 @@
|
|||||||
import adapter from '@sveltejs/adapter-auto';
|
|
||||||
import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';
|
|
||||||
|
|
||||||
/** @type {import('@sveltejs/kit').Config} */
|
|
||||||
const config = {
|
|
||||||
// Consult https://kit.svelte.dev/docs/integrations#preprocessors
|
|
||||||
// for more information about preprocessors
|
|
||||||
preprocess: vitePreprocess(),
|
|
||||||
|
|
||||||
kit: {
|
|
||||||
// adapter-auto only supports some environments, see https://kit.svelte.dev/docs/adapter-auto for a list.
|
|
||||||
// If your environment is not supported or you settled on a specific environment, switch out the adapter.
|
|
||||||
// See https://kit.svelte.dev/docs/adapters for more information about adapters.
|
|
||||||
adapter: adapter()
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export default config;
|
|
@ -1,6 +0,0 @@
|
|||||||
import { expect, test } from '@playwright/test';
|
|
||||||
|
|
||||||
test('index page has expected h1', async ({ page }) => {
|
|
||||||
await page.goto('/');
|
|
||||||
await expect(page.getByRole('heading', { name: 'Welcome to SvelteKit' })).toBeVisible();
|
|
||||||
});
|
|
@ -1,18 +0,0 @@
|
|||||||
{
|
|
||||||
"extends": "./.svelte-kit/tsconfig.json",
|
|
||||||
"compilerOptions": {
|
|
||||||
"allowJs": true,
|
|
||||||
"checkJs": true,
|
|
||||||
"esModuleInterop": true,
|
|
||||||
"forceConsistentCasingInFileNames": true,
|
|
||||||
"resolveJsonModule": true,
|
|
||||||
"skipLibCheck": true,
|
|
||||||
"sourceMap": true,
|
|
||||||
"strict": true,
|
|
||||||
"moduleResolution": "bundler"
|
|
||||||
}
|
|
||||||
// Path aliases are handled by https://kit.svelte.dev/docs/configuration#alias
|
|
||||||
//
|
|
||||||
// If you want to overwrite includes/excludes, make sure to copy over the relevant includes/excludes
|
|
||||||
// from the referenced tsconfig.json - TypeScript does not merge them in
|
|
||||||
}
|
|
@ -1,42 +0,0 @@
|
|||||||
import { sveltekit } from '@sveltejs/kit/vite';
|
|
||||||
import { fileURLToPath, URL } from 'node:url'
|
|
||||||
import { defineConfig } from 'vitest/config';
|
|
||||||
|
|
||||||
/** @type {import('vite').Plugin} */
|
|
||||||
const viteServerConfig = {
|
|
||||||
name: 'log-request-middleware',
|
|
||||||
configureServer(server) {
|
|
||||||
server.middlewares.use((req, res, next) => {
|
|
||||||
res.setHeader("Access-Control-Allow-Origin", "*");
|
|
||||||
res.setHeader("Access-Control-Allow-Methods", "GET");
|
|
||||||
res.setHeader("Cross-Origin-Opener-Policy", "same-origin");
|
|
||||||
res.setHeader("Cross-Origin-Embedder-Policy", "require-corp");
|
|
||||||
next();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
export default defineConfig({
|
|
||||||
plugins: [sveltekit(), viteServerConfig],
|
|
||||||
test: {
|
|
||||||
include: ['src/**/*.{test,spec}.{js,ts}']
|
|
||||||
},
|
|
||||||
resolve: {
|
|
||||||
alias: {
|
|
||||||
'@': fileURLToPath(new URL('./src', import.meta.url))
|
|
||||||
}
|
|
||||||
},
|
|
||||||
optimizeDeps: {
|
|
||||||
exclude: ['@ffmpeg/ffmpeg', '@ffmpeg/util']
|
|
||||||
},
|
|
||||||
server: {
|
|
||||||
headers: {
|
|
||||||
'Cross-Origin-Opener-Policy': 'same-origin',
|
|
||||||
'Cross-Origin-Embedder-Policy': 'require-corp'
|
|
||||||
},
|
|
||||||
fs: {
|
|
||||||
allow: ['../..']
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
17
apps/test/package.json
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"name": "@konoplayer/test",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"private": true,
|
||||||
|
"type": "module",
|
||||||
|
"scripts": {},
|
||||||
|
"dependencies": {
|
||||||
|
"@konoplayer/core": "workspace:*",
|
||||||
|
"@konoplayer/matroska": "workspace:*",
|
||||||
|
"konoebml": "^0.1.2"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"unplugin-swc": "^1.5.1",
|
||||||
|
"vite-tsconfig-paths": "^5.1.4",
|
||||||
|
"vitest": "^3.0.9"
|
||||||
|
}
|
||||||
|
}
|
30
apps/test/tsconfig.json
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
{
|
||||||
|
"extends": "../../tsconfig.base.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"composite": true,
|
||||||
|
"outDir": "./dist",
|
||||||
|
"types": [
|
||||||
|
"vitest/globals",
|
||||||
|
"node"
|
||||||
|
],
|
||||||
|
"paths": {
|
||||||
|
"@konoplayer/core/*": [
|
||||||
|
"../../packages/core/src/*"
|
||||||
|
],
|
||||||
|
"@konoplayer/matroska/*": [
|
||||||
|
"../../packages/matroska/src/*"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"include": [
|
||||||
|
"src"
|
||||||
|
],
|
||||||
|
"references": [
|
||||||
|
{
|
||||||
|
"path": "../../packages/core"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "../../packages/matroska"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
33
apps/test/vitest.config.ts
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
import swc from 'unplugin-swc';
|
||||||
|
import tsconfigPaths from 'vite-tsconfig-paths';
|
||||||
|
import { defineConfig } from 'vitest/config';
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
cacheDir: '.vitest',
|
||||||
|
test: {
|
||||||
|
setupFiles: ['src/init-test'],
|
||||||
|
environment: 'happy-dom',
|
||||||
|
include: ['src/**/*.spec'],
|
||||||
|
globals: true,
|
||||||
|
restoreMocks: true,
|
||||||
|
coverage: {
|
||||||
|
// you can include other reporters, but 'json-summary' is required, json is recommended
|
||||||
|
reporter: ['text', 'json-summary', 'json'],
|
||||||
|
// If you want a coverage reports even if your tests are failing, include the reportOnFailure option
|
||||||
|
reportOnFailure: true,
|
||||||
|
include: ['../../packages/core/src/**', '../../packages/matroska/src/**'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
plugins: [
|
||||||
|
tsconfigPaths(),
|
||||||
|
swc.vite({
|
||||||
|
include: /\.[mc]?[jt]sx?$/,
|
||||||
|
// for git+ package only
|
||||||
|
exclude: [
|
||||||
|
/node_modules\/(?!@konoplayer|\.pnpm)/,
|
||||||
|
/node_modules\/\.pnpm\/(?!@konoplayer)/,
|
||||||
|
] as any,
|
||||||
|
tsconfigFile: './tsconfig.json',
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
});
|
2
apps/vanilla-app/.gitignore
vendored
@ -1,2 +0,0 @@
|
|||||||
*.tgz
|
|
||||||
public/assets
|
|
@ -1,29 +0,0 @@
|
|||||||
# Vanilla / Browser Examples
|
|
||||||
|
|
||||||
## Setup
|
|
||||||
|
|
||||||
You need to download assets from npm before running the examples:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
$ npm run download
|
|
||||||
```
|
|
||||||
|
|
||||||
## Run
|
|
||||||
|
|
||||||
To run this example, execute:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
$ npm start
|
|
||||||
```
|
|
||||||
|
|
||||||
Visit http://localhost:8080 to check available examples.
|
|
||||||
|
|
||||||
## Examples
|
|
||||||
|
|
||||||
| Example | Description |
|
|
||||||
| ------- | ----------- |
|
|
||||||
| transcode.html | Transcoding example |
|
|
||||||
| transcode-mt.html | Transcoding example using multi-thread |
|
|
||||||
| transcode.esm.html | Transcoding example using module |
|
|
||||||
| trim.html | Video trimming example |
|
|
||||||
| concatDemuxer.html | Video concat example |
|
|
@ -1,18 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "browser",
|
|
||||||
"version": "0.12.0-alpha.0",
|
|
||||||
"description": "browser example",
|
|
||||||
"private": true,
|
|
||||||
"scripts": {
|
|
||||||
"download": "node ../../scripts/download-assets.js",
|
|
||||||
"prestart": "npm run download",
|
|
||||||
"start": "node server.js"
|
|
||||||
},
|
|
||||||
"author": "Jerome Wu <jeromewus@gmail.com>",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"express": "^4.18.2",
|
|
||||||
"serve-index": "^1.9.1",
|
|
||||||
"tar": "^6.1.15"
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,54 +0,0 @@
|
|||||||
<html>
|
|
||||||
<head>
|
|
||||||
<link rel="stylesheet" href="style.css">
|
|
||||||
<script src="/assets/ffmpeg/package/dist/umd/ffmpeg.js"></script>
|
|
||||||
<script src="/assets/util/package/dist/umd/index.js"></script>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<h3>Select multiple video files to Concatenate</h3>
|
|
||||||
<video id="output-video" controls></video><br />
|
|
||||||
<input type="file" id="uploader" multiple />
|
|
||||||
<p id="message"></p>
|
|
||||||
<script>
|
|
||||||
const { fetchFile } = FFmpegUtil;
|
|
||||||
const { FFmpeg } = FFmpegWASM;
|
|
||||||
let ffmpeg = null;
|
|
||||||
|
|
||||||
const transcode = async ({ target: { files } }) => {
|
|
||||||
const message = document.getElementById("message");
|
|
||||||
if (ffmpeg === null) {
|
|
||||||
ffmpeg = new FFmpeg();
|
|
||||||
ffmpeg.on("log", ({ message }) => {
|
|
||||||
console.log(message);
|
|
||||||
})
|
|
||||||
ffmpeg.on("progress", ({ progress, time }) => {
|
|
||||||
message.innerHTML = `${time / 1000000} s`;
|
|
||||||
});
|
|
||||||
await ffmpeg.load({
|
|
||||||
coreURL: "/assets/core/package/dist/umd/ffmpeg-core.js",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
message.innerHTML = "Start Concating";
|
|
||||||
const inputPaths = [];
|
|
||||||
for (const file of files) {
|
|
||||||
const { name } = file;
|
|
||||||
ffmpeg.writeFile(name, await fetchFile(file));
|
|
||||||
inputPaths.push(`file ${name}`);
|
|
||||||
}
|
|
||||||
await ffmpeg.writeFile('concat_list.txt', inputPaths.join('\n'));
|
|
||||||
await ffmpeg.exec(['-f', 'concat', '-safe', '0', '-i', 'concat_list.txt', 'output.mp4']);
|
|
||||||
message.innerHTML = "Complete Concating";
|
|
||||||
const data = await ffmpeg.readFile('output.mp4');
|
|
||||||
const video = document.getElementById("output-video");
|
|
||||||
video.src = URL.createObjectURL(
|
|
||||||
new Blob([data.buffer], {
|
|
||||||
type: "video/mp4"
|
|
||||||
})
|
|
||||||
);
|
|
||||||
};
|
|
||||||
const elm = document.getElementById("uploader");
|
|
||||||
elm.addEventListener("change", transcode);
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
@ -1,10 +0,0 @@
|
|||||||
html, body {
|
|
||||||
margin: 0;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%
|
|
||||||
}
|
|
||||||
body {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
@ -1,43 +0,0 @@
|
|||||||
<html>
|
|
||||||
<head>
|
|
||||||
<link rel="stylesheet" href="style.css">
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<h3>Upload a video to transcode to mp4 (x264) and play!</h3>
|
|
||||||
<video id="output-video" controls></video><br/>
|
|
||||||
<input type="file" id="uploader">
|
|
||||||
<p id="message"></p>
|
|
||||||
<script type="module">
|
|
||||||
import { FFmpeg } from "/assets/ffmpeg/package/dist/esm/index.js";
|
|
||||||
import { fetchFile } from "/assets/util/package/dist/esm/index.js";
|
|
||||||
let ffmpeg = null;
|
|
||||||
|
|
||||||
const transcode = async ({ target: { files } }) => {
|
|
||||||
const message = document.getElementById('message');
|
|
||||||
if (ffmpeg === null) {
|
|
||||||
ffmpeg = new FFmpeg();
|
|
||||||
ffmpeg.on("log", ({ message }) => {
|
|
||||||
console.log(message);
|
|
||||||
})
|
|
||||||
ffmpeg.on("progress", ({ progress }) => {
|
|
||||||
message.innerHTML = `${progress * 100} %`;
|
|
||||||
});
|
|
||||||
await ffmpeg.load({
|
|
||||||
coreURL: "/assets/core-mt/package/dist/esm/ffmpeg-core.js",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
const { name } = files[0];
|
|
||||||
await ffmpeg.writeFile(name, await fetchFile(files[0]));
|
|
||||||
message.innerHTML = 'Start transcoding';
|
|
||||||
await ffmpeg.exec(['-i', name, 'output.mp4']);
|
|
||||||
message.innerHTML = 'Complete transcoding';
|
|
||||||
const data = await ffmpeg.readFile('output.mp4');
|
|
||||||
|
|
||||||
const video = document.getElementById('output-video');
|
|
||||||
video.src = URL.createObjectURL(new Blob([data.buffer], { type: 'video/mp4' }));
|
|
||||||
}
|
|
||||||
const elm = document.getElementById('uploader');
|
|
||||||
elm.addEventListener('change', transcode);
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
@ -1,47 +0,0 @@
|
|||||||
<html>
|
|
||||||
<head>
|
|
||||||
<link rel="stylesheet" href="style.css">
|
|
||||||
<script src="/assets/ffmpeg/package/dist/umd/ffmpeg.js"></script>
|
|
||||||
<script src="/assets/util/package/dist/umd/index.js"></script>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<h3>Upload a video to transcode to mp4 (x264) and play!</h3>
|
|
||||||
<video id="output-video" controls></video><br/>
|
|
||||||
<input type="file" id="uploader">
|
|
||||||
<p id="message"></p>
|
|
||||||
<script>
|
|
||||||
const { fetchFile } = FFmpegUtil;
|
|
||||||
const { FFmpeg } = FFmpegWASM;
|
|
||||||
let ffmpeg = null;
|
|
||||||
|
|
||||||
const transcode = async ({ target: { files } }) => {
|
|
||||||
const message = document.getElementById('message');
|
|
||||||
if (ffmpeg === null) {
|
|
||||||
ffmpeg = new FFmpeg();
|
|
||||||
ffmpeg.on("log", ({ message }) => {
|
|
||||||
console.log(message);
|
|
||||||
})
|
|
||||||
ffmpeg.on("progress", ({ progress, time }) => {
|
|
||||||
message.innerHTML = `${progress * 100} %, time: ${time / 1000000} s`;
|
|
||||||
});
|
|
||||||
await ffmpeg.load({
|
|
||||||
coreURL: "/assets/core-mt/package/dist/umd/ffmpeg-core.js",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
const { name } = files[0];
|
|
||||||
await ffmpeg.writeFile(name, await fetchFile(files[0]));
|
|
||||||
message.innerHTML = 'Start transcoding';
|
|
||||||
console.time('exec');
|
|
||||||
await ffmpeg.exec(['-i', name, 'output.mp4']);
|
|
||||||
console.timeEnd('exec');
|
|
||||||
message.innerHTML = 'Complete transcoding';
|
|
||||||
const data = await ffmpeg.readFile('output.mp4');
|
|
||||||
|
|
||||||
const video = document.getElementById('output-video');
|
|
||||||
video.src = URL.createObjectURL(new Blob([data.buffer], { type: 'video/mp4' }));
|
|
||||||
}
|
|
||||||
const elm = document.getElementById('uploader');
|
|
||||||
elm.addEventListener('change', transcode);
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
@ -1,43 +0,0 @@
|
|||||||
<html>
|
|
||||||
<head>
|
|
||||||
<link rel="stylesheet" href="style.css">
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<h3>Upload a video to transcode to mp4 (x264) and play!</h3>
|
|
||||||
<video id="output-video" controls></video><br/>
|
|
||||||
<input type="file" id="uploader">
|
|
||||||
<p id="message"></p>
|
|
||||||
<script type="module">
|
|
||||||
import { FFmpeg } from "/assets/ffmpeg/package/dist/esm/index.js";
|
|
||||||
import { fetchFile } from "/assets/util/package/dist/esm/index.js";
|
|
||||||
let ffmpeg = null;
|
|
||||||
|
|
||||||
const transcode = async ({ target: { files } }) => {
|
|
||||||
const message = document.getElementById('message');
|
|
||||||
if (ffmpeg === null) {
|
|
||||||
ffmpeg = new FFmpeg();
|
|
||||||
ffmpeg.on("log", ({ message }) => {
|
|
||||||
console.log(message);
|
|
||||||
})
|
|
||||||
ffmpeg.on("progress", ({ progress }) => {
|
|
||||||
message.innerHTML = `${progress * 100} %`;
|
|
||||||
});
|
|
||||||
await ffmpeg.load({
|
|
||||||
coreURL: "/assets/core/package/dist/esm/ffmpeg-core.js",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
const { name } = files[0];
|
|
||||||
await ffmpeg.writeFile(name, await fetchFile(files[0]));
|
|
||||||
message.innerHTML = 'Start transcoding';
|
|
||||||
await ffmpeg.exec(['-i', name, 'output.mp4']);
|
|
||||||
message.innerHTML = 'Complete transcoding';
|
|
||||||
const data = await ffmpeg.readFile('output.mp4');
|
|
||||||
|
|
||||||
const video = document.getElementById('output-video');
|
|
||||||
video.src = URL.createObjectURL(new Blob([data.buffer], { type: 'video/mp4' }));
|
|
||||||
}
|
|
||||||
const elm = document.getElementById('uploader');
|
|
||||||
elm.addEventListener('change', transcode);
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
@ -1,47 +0,0 @@
|
|||||||
<html>
|
|
||||||
<head>
|
|
||||||
<link rel="stylesheet" href="style.css">
|
|
||||||
<script src="/assets/ffmpeg/package/dist/umd/ffmpeg.js"></script>
|
|
||||||
<script src="/assets/util/package/dist/umd/index.js"></script>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<h3>Upload a video to transcode to mp4 (x264) and play!</h3>
|
|
||||||
<video id="output-video" controls></video><br/>
|
|
||||||
<input type="file" id="uploader">
|
|
||||||
<p id="message"></p>
|
|
||||||
<script>
|
|
||||||
const { fetchFile } = FFmpegUtil;
|
|
||||||
const { FFmpeg } = FFmpegWASM;
|
|
||||||
let ffmpeg = null;
|
|
||||||
|
|
||||||
const transcode = async ({ target: { files } }) => {
|
|
||||||
const message = document.getElementById('message');
|
|
||||||
if (ffmpeg === null) {
|
|
||||||
ffmpeg = new FFmpeg();
|
|
||||||
ffmpeg.on("log", ({ message }) => {
|
|
||||||
console.log(message);
|
|
||||||
})
|
|
||||||
ffmpeg.on("progress", ({ progress, time }) => {
|
|
||||||
message.innerHTML = `${progress * 100} %, time: ${time / 1000000} s`;
|
|
||||||
});
|
|
||||||
await ffmpeg.load({
|
|
||||||
coreURL: "/assets/core/package/dist/umd/ffmpeg-core.js",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
const { name } = files[0];
|
|
||||||
await ffmpeg.writeFile(name, await fetchFile(files[0]));
|
|
||||||
message.innerHTML = 'Start transcoding';
|
|
||||||
console.time('exec');
|
|
||||||
await ffmpeg.exec(['-i', name, 'output.mp4']);
|
|
||||||
console.timeEnd('exec');
|
|
||||||
message.innerHTML = 'Complete transcoding';
|
|
||||||
const data = await ffmpeg.readFile('output.mp4');
|
|
||||||
|
|
||||||
const video = document.getElementById('output-video');
|
|
||||||
video.src = URL.createObjectURL(new Blob([data.buffer], { type: 'video/mp4' }));
|
|
||||||
}
|
|
||||||
const elm = document.getElementById('uploader');
|
|
||||||
elm.addEventListener('change', transcode);
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
@ -1,45 +0,0 @@
|
|||||||
<html>
|
|
||||||
<head>
|
|
||||||
<link rel="stylesheet" href="style.css">
|
|
||||||
<script src="/assets/ffmpeg/package/dist/umd/ffmpeg.js"></script>
|
|
||||||
<script src="/assets/util/package/dist/umd/index.js"></script>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<h3>Upload a mp4 (x264) video and trim its first 1 seconds and play!</h3>
|
|
||||||
<video id="output-video" controls></video><br/>
|
|
||||||
<input type="file" id="uploader">
|
|
||||||
<p id="message"></p>
|
|
||||||
<script>
|
|
||||||
const { fetchFile } = FFmpegUtil;
|
|
||||||
const { FFmpeg } = FFmpegWASM;
|
|
||||||
let ffmpeg = null;
|
|
||||||
|
|
||||||
const trim = async ({ target: { files } }) => {
|
|
||||||
const message = document.getElementById('message');
|
|
||||||
if (ffmpeg === null) {
|
|
||||||
ffmpeg = new FFmpeg();
|
|
||||||
ffmpeg.on("log", ({ message }) => {
|
|
||||||
console.log(message);
|
|
||||||
})
|
|
||||||
ffmpeg.on("progress", ({ progress }) => {
|
|
||||||
message.innerHTML = `${progress * 100} %`;
|
|
||||||
});
|
|
||||||
await ffmpeg.load({
|
|
||||||
coreURL: "/assets/core/package/dist/umd/ffmpeg-core.js",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
const { name } = files[0];
|
|
||||||
await ffmpeg.writeFile(name, await fetchFile(files[0]));
|
|
||||||
message.innerHTML = 'Start trimming';
|
|
||||||
await ffmpeg.exec(['-i', name, '-ss', '0', '-to', '1', 'output.mp4']);
|
|
||||||
message.innerHTML = 'Complete trimming';
|
|
||||||
const data = await ffmpeg.readFile('output.mp4');
|
|
||||||
|
|
||||||
const video = document.getElementById('output-video');
|
|
||||||
video.src = URL.createObjectURL(new Blob([data.buffer], { type: 'video/mp4' }));
|
|
||||||
}
|
|
||||||
const elm = document.getElementById('uploader');
|
|
||||||
elm.addEventListener('change', trim);
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
@ -1,27 +0,0 @@
|
|||||||
const path = require("path");
|
|
||||||
const express = require("express");
|
|
||||||
const serveIndex = require("serve-index");
|
|
||||||
const app = express();
|
|
||||||
const PORT = 8080;
|
|
||||||
const ROOT = path.join(__dirname, "public");
|
|
||||||
|
|
||||||
app.use((_, res, next) => {
|
|
||||||
res.set({
|
|
||||||
"Cross-Origin-Opener-Policy": "same-origin",
|
|
||||||
"Cross-Origin-Embedder-Policy": "require-corp",
|
|
||||||
"Cross-Origin-Resource-Policy": "cross-origin",
|
|
||||||
"Origin-Agent-Cluster": "?1",
|
|
||||||
"Access-Control-Allow-Origin": "*",
|
|
||||||
"Access-Control-Allow-Methods": "GET, POST, OPTIONS",
|
|
||||||
"Access-Control-Allow-Headers":
|
|
||||||
"Origin, X-Requested-With, Content-Type, Accept, Range",
|
|
||||||
});
|
|
||||||
next();
|
|
||||||
});
|
|
||||||
|
|
||||||
app.use(express.static(ROOT));
|
|
||||||
app.use("/", serveIndex(ROOT));
|
|
||||||
|
|
||||||
app.listen(PORT, () => {
|
|
||||||
console.log(`Listening on port ${PORT}`);
|
|
||||||
});
|
|