Skip to content

Commit 49b3d30

Browse files
wip
1 parent c9be241 commit 49b3d30

File tree

16 files changed

+307
-236
lines changed

16 files changed

+307
-236
lines changed

apps/web/app/(org)/dashboard/caps/components/UploadCapButton.tsx

Lines changed: 77 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -104,29 +104,42 @@ async function legacyUploadCap(
104104
setUploadStatus: (state: UploadStatus | undefined) => void,
105105
queryClient: QueryClient,
106106
) {
107-
const parser = await import("@remotion/media-parser");
108-
const webcodecs = await import("@remotion/webcodecs");
107+
const { Input } = await import("mediabunny");
109108

110109
try {
111110
setUploadStatus({ status: "parsing" });
112-
const metadata = await parser.parseMedia({
113-
src: file,
114-
fields: {
115-
durationInSeconds: true,
116-
dimensions: true,
117-
fps: true,
118-
numberOfAudioChannels: true,
119-
sampleRate: true,
120-
},
111+
const { BlobSource, ALL_FORMATS } = await import("mediabunny");
112+
const input = new Input({
113+
source: new BlobSource(file),
114+
formats: ALL_FORMATS,
121115
});
122116

123-
const duration = metadata.durationInSeconds
117+
// Get metadata from the input
118+
const videoTracks = await input.getVideoTracks();
119+
const audioTracks = await input.getAudioTracks();
120+
const videoTrack = videoTracks[0];
121+
const audioTrack = audioTracks[0];
122+
const fileDuration = await input.computeDuration();
123+
124+
const metadata = {
125+
durationInSeconds: fileDuration,
126+
dimensions: videoTrack
127+
? { width: videoTrack.displayWidth, height: videoTrack.displayHeight }
128+
: undefined,
129+
fps: videoTrack
130+
? (await videoTrack.computePacketStats()).averagePacketRate
131+
: undefined,
132+
numberOfAudioChannels: audioTrack?.numberOfChannels,
133+
sampleRate: audioTrack?.sampleRate,
134+
};
135+
136+
const videoDuration = metadata.durationInSeconds
124137
? Math.round(metadata.durationInSeconds)
125138
: undefined;
126139

127140
setUploadStatus({ status: "creating" });
128141
const videoData = await createVideoAndGetUploadUrl({
129-
duration,
142+
duration: videoDuration,
130143
resolution: metadata.dimensions
131144
? `${metadata.dimensions.width}x${metadata.dimensions.height}`
132145
: undefined,
@@ -165,24 +178,59 @@ async function legacyUploadCap(
165178

166179
const resizeOptions = calculateResizeOptions();
167180

168-
const convertResult = await webcodecs.convertMedia({
169-
src: file,
170-
container: "mp4",
171-
videoCodec: "h264",
172-
audioCodec: "aac",
173-
...(resizeOptions && { resize: resizeOptions }),
174-
onProgress: ({ overallProgress }) => {
175-
if (overallProgress !== null) {
176-
const progressValue = overallProgress * 100;
177-
setUploadStatus({
178-
status: "converting",
179-
capId: uploadId,
180-
progress: progressValue,
181-
});
182-
}
181+
const {
182+
Output,
183+
Mp4OutputFormat,
184+
BufferTarget,
185+
Conversion,
186+
BlobSource,
187+
ALL_FORMATS,
188+
} = await import("mediabunny");
189+
const input = new Input({
190+
source: new BlobSource(file),
191+
formats: ALL_FORMATS,
192+
});
193+
const output = new Output({
194+
format: new Mp4OutputFormat(),
195+
target: new BufferTarget(),
196+
});
197+
198+
const conversion = await Conversion.init({
199+
input,
200+
output,
201+
video: {
202+
codec: "avc",
203+
...(resizeOptions && {
204+
width: Math.round(metadata.dimensions!.width * resizeOptions.scale),
205+
height: Math.round(
206+
metadata.dimensions!.height * resizeOptions.scale,
207+
),
208+
}),
209+
},
210+
audio: {
211+
codec: "aac",
183212
},
184213
});
185-
optimizedBlob = await convertResult.save();
214+
215+
if (!conversion.isValid) {
216+
throw new Error("Video conversion configuration is invalid");
217+
}
218+
219+
conversion.onProgress = (progress) => {
220+
const progressValue = progress * 100;
221+
setUploadStatus({
222+
status: "converting",
223+
capId: uploadId,
224+
progress: progressValue,
225+
});
226+
};
227+
228+
await conversion.execute();
229+
const buffer = output.target.buffer;
230+
if (!buffer) {
231+
throw new Error("Conversion produced no output buffer");
232+
}
233+
optimizedBlob = new Blob([buffer]);
186234

187235
if (optimizedBlob.size === 0)
188236
throw new Error("Conversion produced empty file");

apps/web/app/(org)/verify-otp/form.tsx

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -75,12 +75,24 @@ export function VerifyOTPForm({
7575
const otpCode = code.join("");
7676
if (otpCode.length !== 6) throw "Please enter a complete 6-digit code";
7777

78-
// shoutout https://github.com/buoyad/Tally/pull/14
79-
const res = await fetch(
80-
`/api/auth/callback/email?email=${encodeURIComponent(email)}&token=${encodeURIComponent(otpCode)}&callbackUrl=${encodeURIComponent("/login-success")}`,
81-
);
78+
const callback = next || "/dashboard";
79+
const url = `/api/auth/callback/email?email=${encodeURIComponent(email)}&token=${encodeURIComponent(otpCode)}&callbackUrl=${encodeURIComponent(callback)}`;
8280

83-
if (!res.url.includes("/login-success")) {
81+
const isSafari =
82+
typeof navigator !== "undefined" &&
83+
/^((?!chrome|android).)*safari/i.test(navigator.userAgent);
84+
85+
if (isSafari) {
86+
window.location.assign(url);
87+
return;
88+
}
89+
90+
const res = await fetch(url, {
91+
credentials: "include",
92+
redirect: "follow",
93+
});
94+
95+
if (!res.url.includes(callback)) {
8496
setCode(["", "", "", "", "", ""]);
8597
inputRefs.current[0]?.focus();
8698
throw "Invalid code. Please try again.";

apps/web/app/(site)/tools/convert/[conversionPath]/page.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ export default async function ConversionPage(props: ConversionPageProps) {
9797
faqs: [
9898
{
9999
question: `How does the ${sourceFormat.toUpperCase()} to ${targetFormat.toUpperCase()} converter work?`,
100-
answer: `Our converter uses Remotion (remotion.dev) directly in your browser. When you upload a ${sourceFormat.toUpperCase()} file, it gets processed locally on your device and converted to ${targetFormat.toUpperCase()} format without ever being sent to a server.`,
100+
answer: `Our converter uses Mediabunny (mediabunny.dev) directly in your browser. When you upload a ${sourceFormat.toUpperCase()} file, it gets processed locally on your device and converted to ${targetFormat.toUpperCase()} format without ever being sent to a server.`,
101101
},
102102
{
103103
question: "Is there a file size limit?",

apps/web/app/(site)/tools/convert/avi-to-mp4/page.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ export default function AVIToMP4Page() {
5757
{
5858
question: "How does the AVI to MP4 converter work?",
5959
answer:
60-
"Our converter uses Remotion (remotion.dev) directly in your browser. When you upload an AVI file, it gets processed locally on your device and converted to MP4 format without ever being sent to a server.",
60+
"Our converter uses Mediabunny (mediabunny.dev) directly in your browser. When you upload an AVI file, it gets processed locally on your device and converted to MP4 format without ever being sent to a server.",
6161
},
6262
{
6363
question: "Is there a file size limit?",

apps/web/app/(site)/tools/convert/mkv-to-mp4/page.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ export default function MKVToMP4Page() {
5757
{
5858
question: "How does the MKV to MP4 converter work?",
5959
answer:
60-
"Our converter uses Remotion (remotion.dev) directly in your browser. When you upload an MKV file, it gets processed locally on your device and converted to MP4 format without ever being sent to a server.",
60+
"Our converter uses Mediabunny (mediabunny.dev) directly in your browser. When you upload an MKV file, it gets processed locally on your device and converted to MP4 format without ever being sent to a server.",
6161
},
6262
{
6363
question: "Is there a file size limit?",

apps/web/app/(site)/tools/convert/mov-to-mp4/page.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ export default function MOVToMP4Page() {
5757
{
5858
question: "How does the MOV to MP4 converter work?",
5959
answer:
60-
"Our converter uses Remotion (remotion.dev) directly in your browser. When you upload a MOV file, it gets processed locally on your device and converted to MP4 format without ever being sent to a server.",
60+
"Our converter uses Mediabunny (mediabunny.dev) directly in your browser. When you upload a MOV file, it gets processed locally on your device and converted to MP4 format without ever being sent to a server.",
6161
},
6262
{
6363
question: "Is there a file size limit?",

apps/web/app/(site)/tools/convert/mp4-to-gif/page.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,14 +51,14 @@ export default function MP4ToGIFPage() {
5151
{
5252
title: "High Quality Conversion",
5353
description:
54-
"We use Remotion technology to create optimized GIFs from your videos.",
54+
"We use Mediabunny technology to create optimized GIFs from your videos.",
5555
},
5656
],
5757
faqs: [
5858
{
5959
question: "How does the MP4 to GIF converter work?",
6060
answer:
61-
"Our converter uses Remotion (remotion.dev) directly in your browser. When you upload an MP4 file, it gets processed locally on your device and converted to an animated GIF without ever being sent to a server.",
61+
"Our converter uses Mediabunny (mediabunny.dev) directly in your browser. When you upload an MP4 file, it gets processed locally on your device and converted to an animated GIF without ever being sent to a server.",
6262
},
6363
{
6464
question: "Is there a file size limit?",

apps/web/app/(site)/tools/convert/mp4-to-mp3/page.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,14 +50,14 @@ export default function MP4ToMP3Page() {
5050
{
5151
title: "High Quality Conversion",
5252
description:
53-
"We use Remotion technology to ensure high-quality audio extraction.",
53+
"We use Mediabunny technology to ensure high-quality audio extraction.",
5454
},
5555
],
5656
faqs: [
5757
{
5858
question: "How does the MP4 to MP3 converter work?",
5959
answer:
60-
"Our converter uses Remotion (remotion.dev) directly in your browser. When you upload an MP4 file, it extracts the audio track locally on your device and saves it as an MP3 file without ever being sent to a server.",
60+
"Our converter uses Mediabunny (mediabunny.dev) directly in your browser. When you upload an MP4 file, it extracts the audio track locally on your device and saves it as an MP3 file without ever being sent to a server.",
6161
},
6262
{
6363
question: "Is there a file size limit?",

apps/web/app/(site)/tools/convert/mp4-to-webm/page.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ export default function MP4ToWebMPage() {
5757
{
5858
question: "How does the MP4 to WebM converter work?",
5959
answer:
60-
"Our converter uses Remotion (remotion.dev) directly in your browser. When you upload an MP4 file, it gets processed locally on your device and converted to WebM format without ever being sent to a server.",
60+
"Our converter uses Mediabunny (mediabunny.dev) directly in your browser. When you upload an MP4 file, it gets processed locally on your device and converted to WebM format without ever being sent to a server.",
6161
},
6262
{
6363
question: "Is there a file size limit?",

apps/web/app/(site)/tools/convert/webm-to-mp4/page.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ export default function WebmToMp4Page() {
5757
{
5858
question: "How does the WebM to MP4 converter work?",
5959
answer:
60-
"Our converter uses Remotion (remotion.dev) directly in your browser. When you upload a WebM file, it gets processed locally on your device and converted to MP4 format without ever being sent to a server.",
60+
"Our converter uses Mediabunny (mediabunny.dev) directly in your browser. When you upload a WebM file, it gets processed locally on your device and converted to MP4 format without ever being sent to a server.",
6161
},
6262
{
6363
question: "Is there a file size limit?",

0 commit comments

Comments
 (0)