fix recording duration and make it seekable
This commit is contained in:
parent
e2ec7d12b8
commit
74d73b89c6
3 changed files with 1528 additions and 27 deletions
1508
package-lock.json
generated
1508
package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
|
@ -38,8 +38,8 @@
|
||||||
"axios": "^1.3.5",
|
"axios": "^1.3.5",
|
||||||
"crisp-sdk-web": "^1.0.18",
|
"crisp-sdk-web": "^1.0.18",
|
||||||
"dayjs": "^1.11.7",
|
"dayjs": "^1.11.7",
|
||||||
|
"ebml": "^3.0.0",
|
||||||
"file-saver": "^2.0.5",
|
"file-saver": "^2.0.5",
|
||||||
"fix-webm-duration": "^1.0.5",
|
|
||||||
"jotai": "^2.0.4",
|
"jotai": "^2.0.4",
|
||||||
"micro": "^10.0.1",
|
"micro": "^10.0.1",
|
||||||
"micro-cors": "^0.1.1",
|
"micro-cors": "^0.1.1",
|
||||||
|
|
@ -56,6 +56,7 @@
|
||||||
"stripe": "^12.12.0",
|
"stripe": "^12.12.0",
|
||||||
"superjson": "1.12.2",
|
"superjson": "1.12.2",
|
||||||
"tailwindcss-radix": "^2.8.0",
|
"tailwindcss-radix": "^2.8.0",
|
||||||
|
"ts-ebml": "^2.0.2",
|
||||||
"zod": "^3.21.4"
|
"zod": "^3.21.4"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|
|
||||||
|
|
@ -10,14 +10,14 @@ import axios from "axios";
|
||||||
import dayjs from "dayjs";
|
import dayjs from "dayjs";
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import { api } from "~/utils/api";
|
import { api } from "~/utils/api";
|
||||||
import fixWebmDuration from "fix-webm-duration";
|
|
||||||
import { TRPCClientError } from "@trpc/client";
|
import { TRPCClientError } from "@trpc/client";
|
||||||
import { useAtom } from "jotai/index";
|
import { useAtom } from "jotai";
|
||||||
import paywallAtom from "~/atoms/paywallAtom";
|
import paywallAtom from "~/atoms/paywallAtom";
|
||||||
import recordVideoModalOpen from "~/atoms/recordVideoModalOpen";
|
import recordVideoModalOpen from "~/atoms/recordVideoModalOpen";
|
||||||
import { usePostHog } from "posthog-js/react";
|
import { usePostHog } from "posthog-js/react";
|
||||||
import Tooltip from "~/components/Tooltip";
|
import Tooltip from "~/components/Tooltip";
|
||||||
import generateThumbnail from "~/utils/generateThumbnail";
|
import generateThumbnail from "~/utils/generateThumbnail";
|
||||||
|
import * as EBML from "ts-ebml";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
closeModal: () => void;
|
closeModal: () => void;
|
||||||
|
|
@ -103,17 +103,43 @@ export default function Recorder({ closeModal, step, setStep }: Props) {
|
||||||
posthog?.capture("recorder: start video recording");
|
posthog?.capture("recorder: start video recording");
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function getSeekableBlob(inputBlob: Blob, callback: (blob: Blob) => void) {
|
||||||
|
const reader = new EBML.Reader();
|
||||||
|
const decoder = new EBML.Decoder();
|
||||||
|
const tools = EBML.tools;
|
||||||
|
|
||||||
|
const fileReader = new FileReader();
|
||||||
|
fileReader.onload = function (e) {
|
||||||
|
if (!this.result || typeof this.result === "string") return;
|
||||||
|
const ebmlElms = decoder.decode(this.result);
|
||||||
|
ebmlElms.forEach(function (element) {
|
||||||
|
reader.read(element);
|
||||||
|
});
|
||||||
|
reader.stop();
|
||||||
|
|
||||||
|
const refinedMetadataBuf = tools.makeMetadataSeekable(
|
||||||
|
reader.metadatas,
|
||||||
|
duration * 1000,
|
||||||
|
reader.cues
|
||||||
|
);
|
||||||
|
|
||||||
|
const body = this.result.slice(reader.metadataSize);
|
||||||
|
const newBlob = new Blob([refinedMetadataBuf, body], {
|
||||||
|
type: "video/webm",
|
||||||
|
});
|
||||||
|
|
||||||
|
callback(newBlob);
|
||||||
|
};
|
||||||
|
fileReader.readAsArrayBuffer(inputBlob);
|
||||||
|
}
|
||||||
|
|
||||||
const handleStop = () => {
|
const handleStop = () => {
|
||||||
if (recorderRef.current === null) return;
|
if (recorderRef.current === null) return;
|
||||||
recorderRef.current.stopRecording(() => {
|
recorderRef.current.stopRecording(() => {
|
||||||
if (recorderRef.current) {
|
if (recorderRef.current) {
|
||||||
fixWebmDuration(
|
getSeekableBlob(recorderRef.current.getBlob(), function (fixedBlob) {
|
||||||
recorderRef.current.getBlob(),
|
setBlob(fixedBlob);
|
||||||
duration * 1000,
|
});
|
||||||
(seekableBlob) => {
|
|
||||||
setBlob(seekableBlob);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
steam?.getTracks().map((track) => track.stop());
|
steam?.getTracks().map((track) => track.stop());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue