Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
JonnyBurger committed Dec 12, 2024
2 parents 897e91b + 0dd9ea7 commit 6891e52
Show file tree
Hide file tree
Showing 11 changed files with 240 additions and 10 deletions.
Binary file modified packages/cloudrun/src/gcpInstaller/gcpInstaller.tar
Binary file not shown.
20 changes: 20 additions & 0 deletions packages/convert/app/entry.client.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { RemixBrowser } from "@remix-run/react";
import { hydrateRoot } from "react-dom/client";
import { startTransition } from "react";

const registerServiceWorker = () => {
if ("serviceWorker" in navigator) {
window.addEventListener("load", () => {
navigator.serviceWorker
.register("/convert/service-worker.js")
.catch((error) => {
console.log("SW registration failed:", error);
});
});
}
};

startTransition(() => {
hydrateRoot(document, <RemixBrowser />);
registerServiceWorker();
});
6 changes: 4 additions & 2 deletions packages/convert/app/root.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {Links, Outlet, Scripts, ScrollRestoration} from '@remix-run/react';
import './tailwind.css';

import {Links, Outlet, Scripts, ScrollRestoration} from '@remix-run/react';

export function Layout({children}: {readonly children: React.ReactNode}) {
return (
<html lang="en">
Expand All @@ -9,7 +10,8 @@ export function Layout({children}: {readonly children: React.ReactNode}) {
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Remotion Convert</title>
<meta name="description" content="Remotion Convert" />
<link rel="icon" href="https://www.remotion.dev/img/favicon.png" />
<link rel="icon" href="/convert/pwa-icon-192.png" />
<link rel="manifest" href="/convert/manifest.json" />
<Links />
</head>
<body>
Expand Down
104 changes: 104 additions & 0 deletions packages/convert/app/service-worker.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-nocheck
const $FILES = [];
// ^ leave this - will get filled in during build
// --auto-generated-until-here

const CACHE_NAME = 'remotion-convert-v1';

// Helper function to determine if a request is under /convert
function isConvertPath(url) {
return url.pathname.startsWith('/convert');
}

self.addEventListener('install', (event) => {
event.waitUntil(
(async () => {
const cache = await caches.open(CACHE_NAME);
await cache.addAll($FILES);
// @ts-expect-error no types
await self.skipWaiting();
})(),
);
});

self.addEventListener('activate', (event) => {
event.waitUntil(
(async () => {
// Clean up old caches
const cacheNames = await caches.keys();
await Promise.all(
cacheNames
.filter((name) => name !== CACHE_NAME)
.map((name) => caches.delete(name)),
);
// Take control of all pages immediately
// @ts-expect-error no types
await self.clients.claim();
})(),
);
});

self.addEventListener('fetch', (event) => {
const url = new URL(event.request.url);

if (!isConvertPath(url)) {
return;
}

// Only handle same-origin requests
if (!url.origin.includes(self.location.origin)) {
return;
}

// If it is a file selected from the user's device, do not cache it
if (url.protocol === 'file:') {
return;
}

// Special handling for /convert paths
if (isConvertPath(url)) {
event.respondWith(
(async () => {
try {
// Try to fetch the network request
const response = await fetch(event.request);

// Cache the new response
const cache = await caches.open(CACHE_NAME);
await cache.put(event.request, response.clone());

return response;
} catch {
// If network fails, try cache
const cachedResponse = await caches.match(event.request);
if (cachedResponse) {
return cachedResponse;
}

// If both network and cache fail, return a basic offline response
if (event.request.headers.get('accept')?.includes('text/html')) {
return caches.match('/convert');
}

return new Response('Network error happened', {
status: 408,
headers: {'Content-Type': 'text/plain'},
});
}
})(),
);
return;
}

// For all other requests, do a simple network-first strategy
event.respondWith(
(async () => {
try {
return await fetch(event.request);
} catch {
return caches.match(event.request);
}
})(),
);
});
43 changes: 43 additions & 0 deletions packages/convert/build-service-worker.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import fs from 'fs';
const files = fs.readdirSync('spa-dist/client');
const assets = fs.readdirSync('spa-dist/client/assets');
const toCache = [
...files
.filter((f) => {
return fs.statSync(`spa-dist/client/${f}`).isFile();
})
.map((f) => `/convert/${f}`.replace('/index.html', '')),
...assets
.filter((f) => {
if (!fs.statSync(`spa-dist/client/assets/${f}`).isFile()) {
throw new Error('Unexpected output');
}
return true;
})
.map((f) => `/convert/assets/${f}`),
];

const result = await Bun.build({
entrypoints: ['./app/service-worker.ts'],
});

if (!result.success) {
console.log(result.logs);
throw new Error('Failed to build service worker');
}

const firstOutput = result.outputs[0];

if (!firstOutput) {
throw new Error('No output');
}
const text = await firstOutput.text();
const replaced = '$FILES = [];';
if (!text.includes(replaced)) {
throw new Error('Unexpected output');
}

await Bun.write(
'spa-dist/client/service-worker.js',
text.replace(replaced, `$FILES = ${JSON.stringify(toCache)};`),
);
2 changes: 1 addition & 1 deletion packages/convert/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"type": "module",
"scripts": {
"build-page": "remix vite:build",
"build-spa": "remix vite:build -c vite-spa.config.ts",
"build-spa": "remix vite:build -c vite-spa.config.ts && bun build-service-worker.ts",
"dev": "remix vite:dev",
"typecheck": "tsc",
"test": "bun test test",
Expand Down
28 changes: 28 additions & 0 deletions packages/convert/public/manifest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"name": "Remotion Convert",
"id": "com.remotion.convert",
"short_name": "Remotion Convert",
"description": "Convert videos using WebCodecs",
"start_url": "/convert",
"display": "standalone",
"background_color": "#ffffff",
"theme_color": "#0B84F3",
"icons": [
{
"src": "/convert/pwa-icon-192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "/convert/pwa-icon-512.png",
"sizes": "512x512",
"type": "image/png"
},
{
"src": "/convert/pwa-icon-512.png",
"sizes": "512x512",
"type": "image/png",
"purpose": "maskable"
}
]
}
Binary file added packages/convert/public/pwa-icon-192.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added packages/convert/public/pwa-icon-512.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion packages/convert/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"test"
],
"compilerOptions": {
"lib": ["DOM", "DOM.Iterable", "ES2022"],
"lib": ["WebWorker", "DOM", "DOM.Iterable", "ES2022"],
"types": ["@remix-run/node", "vite/client", "@types/bun"],
"isolatedModules": true,
"esModuleInterop": true,
Expand Down
45 changes: 39 additions & 6 deletions packages/webcodecs/src/auto-select-writer.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import {bufferWriter} from '@remotion/media-parser/buffer';
import {canUseWebFsWriter, webFsWriter} from '@remotion/media-parser/web-fs';

import type {WriterInterface} from '@remotion/media-parser';
import {
MediaParserInternals,
type WriterInterface,
} from '@remotion/media-parser';
import {bufferWriter} from '@remotion/media-parser/buffer';
import type {LogLevel} from './log';
import {Log} from './log';

Expand All @@ -15,14 +18,44 @@ export const autoSelectWriter = async (
}

Log.verbose(logLevel, 'Determining best writer');
if (await canUseWebFsWriter()) {
Log.verbose(logLevel, 'Using WebFS writer because it is supported');
return webFsWriter;

// Check if we're offline using the navigator API
const isOffline = !navigator.onLine;

if (isOffline) {
Log.verbose(logLevel, 'Offline mode detected, using buffer writer');
return bufferWriter;
}

try {
const {
promise: timeout,
reject,
resolve,
} = MediaParserInternals.withResolvers<void>();
const time = setTimeout(
() => reject(new Error('WebFS check timeout')),
2000,
);

const webFsSupported = await Promise.race([canUseWebFsWriter(), timeout]);
resolve();
clearTimeout(time);

if (webFsSupported) {
Log.verbose(logLevel, 'Using WebFS writer because it is supported');
return webFsWriter;
}
} catch (err) {
Log.verbose(
logLevel,
`WebFS check failed: ${err}. Falling back to buffer writer`,
);
}

Log.verbose(
logLevel,
'Using buffer writer because WebFS writer is not supported',
'Using buffer writer because WebFS writer is not supported or unavailable',
);
return bufferWriter;
};

0 comments on commit 6891e52

Please sign in to comment.