From bb47ce583c9b1a07ccc67781ad65100c66f718d9 Mon Sep 17 00:00:00 2001 From: Carla Paiva Date: Sat, 27 Jan 2024 19:21:20 -0300 Subject: [PATCH 1/2] wip --- .../converter/converter-steps/index.tsx | 6 ++++-- .../upload-step/upload-step.tsx | 5 +++-- src/components/converter/index.tsx | 10 ++++++---- src/components/video-converter/index.tsx | 20 +++++++++++++++++++ src/services/converter.ts | 4 ++-- 5 files changed, 35 insertions(+), 10 deletions(-) diff --git a/src/components/converter/converter-steps/index.tsx b/src/components/converter/converter-steps/index.tsx index 9e48cf2..7617bae 100644 --- a/src/components/converter/converter-steps/index.tsx +++ b/src/components/converter/converter-steps/index.tsx @@ -18,6 +18,7 @@ type ConverterStepsProps = { convert: () => Promise clearStates: () => void downloadFiles: () => void + updateSelectedExtension: (extension: string) => void } const ConverterSteps = memo(function ConverterStepsComponent(props: ConverterStepsProps): JSX.Element { @@ -43,8 +44,9 @@ const ConverterSteps = memo(function ConverterStepsComponent(props: ConverterSte allowedUploadingFormats={props.allowedUploadingFormats} extensionOptions={props.extensionOptions} onConvertClick={onConvertClick} - populateFileList={props.populateFileList} /> - }, [props.allowedUploadingFormats, props.extensionOptions, props.populateFileList, onConvertClick]) + populateFileList={props.populateFileList} + updateSelectedExtension={props.updateSelectedExtension} /> + }, [props.allowedUploadingFormats, props.extensionOptions, props.populateFileList, props.updateSelectedExtension, onConvertClick]) const getResultStep = useCallback(() => { return void onConvertClick: () => void + updateSelectedExtension: (extension: string) => void } type ErrorMessage = { @@ -48,7 +49,6 @@ const UploadStep = memo(function UploadStepComponent(props: Readonly { if (index === props.allowedUploadingFormats.length - 1) { types += type - return } types += type + ", " @@ -59,7 +59,8 @@ const UploadStep = memo(function UploadStepComponent(props: Readonly { setFormat(value) - }, []) + props.updateSelectedExtension(value) + }, [props]) const onClick = useCallback(() => { diff --git a/src/components/converter/index.tsx b/src/components/converter/index.tsx index 00f98d1..8c676f5 100644 --- a/src/components/converter/index.tsx +++ b/src/components/converter/index.tsx @@ -17,7 +17,8 @@ type ConverterProps = { const Converter = memo(function ConverterComponent(props: ConverterProps): JSX.Element { const [fileList, setFileList] = useState([]) const [convertedFiles, setConvertedFiles ] = useState([]) - + const [selectedExtension, setSelectedExtension ] = useState('') + const onUploadDone = useCallback((files: UploadFile[]) => { setFileList(files) }, []) @@ -35,9 +36,9 @@ const Converter = memo(function ConverterComponent(props: ConverterProps): JSX.E }, []) const convert = useCallback(async () => { - const files = await convertFiles(fileList) + const files = await convertFiles(fileList, selectedExtension) setConvertedFiles(files) - }, [fileList]) + }, [fileList, selectedExtension]) const downloadFiles = useCallback(() => { convertedFiles.forEach(file => { @@ -62,7 +63,8 @@ const Converter = memo(function ConverterComponent(props: ConverterProps): JSX.E populateFileList={onUploadDone} convert={convert} clearStates={clearStates} - downloadFiles={downloadFiles} /> + downloadFiles={downloadFiles} + updateSelectedExtension={setSelectedExtension} /> ) }) diff --git a/src/components/video-converter/index.tsx b/src/components/video-converter/index.tsx index fd8cb59..97373f8 100644 --- a/src/components/video-converter/index.tsx +++ b/src/components/video-converter/index.tsx @@ -10,6 +10,26 @@ const optionsToConvertTo: Format[] = [ name: "GIF", extension: ".gif", mimeType: "image/gif" + }, + { + name: "MP4", + extension: ".mp4", + mimeType: "video/mp4" + }, + { + name: "AVI", + extension: ".avi", + mimeType: "video/x-msvideo" + }, + { + name: "WMV", + extension: ".wmv", + mimeType: "video/x-ms-asf" + }, + { + name: "MP3", + extension: ".mp3", + mimeType: "audio/mp4" } ] diff --git a/src/services/converter.ts b/src/services/converter.ts index 63c2884..42d1112 100644 --- a/src/services/converter.ts +++ b/src/services/converter.ts @@ -2,14 +2,14 @@ import { createFFmpeg } from "@ffmpeg/ffmpeg"; import { UploadFile } from "antd"; import { ConvertedFile } from "../model/converted-file"; -async function convertFiles(fileList: UploadFile[]): Promise{ +async function convertFiles(fileList: UploadFile[], extension: string): Promise{ const blobList: ConvertedFile[] = [] for (const file of fileList) { const sourceBuffer = await file.originFileObj?.arrayBuffer() as ArrayBuffer console.log('sourceBuffer', sourceBuffer) const nameWithoutExt = file.name.split('.')[0] - const outputName = `${nameWithoutExt}.gif` + const outputName = `${nameWithoutExt}${extension}` const ffmpeg = createFFmpeg({ log: true }); await ffmpeg.load(); From da27dcd918ca8d0e8785285d9aed85ab41a5ddd7 Mon Sep 17 00:00:00 2001 From: Carla Paiva Date: Sat, 27 Jan 2024 19:49:52 -0300 Subject: [PATCH 2/2] feat: add video converter --- src/components/converter-content/index.tsx | 2 +- .../upload-step/upload-step.tsx | 1 + src/components/video-converter/index.tsx | 19 +++++------- src/model/format.ts | 2 -- src/services/converter.ts | 29 +++++++++++++++---- 5 files changed, 33 insertions(+), 20 deletions(-) diff --git a/src/components/converter-content/index.tsx b/src/components/converter-content/index.tsx index 66a7ebc..dc7a0f7 100644 --- a/src/components/converter-content/index.tsx +++ b/src/components/converter-content/index.tsx @@ -4,7 +4,7 @@ import VideoConverter from '../video-converter'; const items = [ { - label: 'Video To GIF', + label: 'Video Converter', key: '1', children: } diff --git a/src/components/converter/converter-steps/upload-step/upload-step.tsx b/src/components/converter/converter-steps/upload-step/upload-step.tsx index f621da9..09c0d48 100644 --- a/src/components/converter/converter-steps/upload-step/upload-step.tsx +++ b/src/components/converter/converter-steps/upload-step/upload-step.tsx @@ -49,6 +49,7 @@ const UploadStep = memo(function UploadStepComponent(props: Readonly { if (index === props.allowedUploadingFormats.length - 1) { types += type + return } types += type + ", " diff --git a/src/components/video-converter/index.tsx b/src/components/video-converter/index.tsx index 97373f8..e081ca0 100644 --- a/src/components/video-converter/index.tsx +++ b/src/components/video-converter/index.tsx @@ -2,34 +2,31 @@ import { Format } from "../../model/format" import Converter from "../converter" const uploadingFormat: string[] = [ - ".mp4" + "video/mp4", + "video/x-m4v", + "video/*" ] const optionsToConvertTo: Format[] = [ { name: "GIF", - extension: ".gif", - mimeType: "image/gif" + extension: ".gif" }, { name: "MP4", - extension: ".mp4", - mimeType: "video/mp4" + extension: ".mp4" }, { name: "AVI", - extension: ".avi", - mimeType: "video/x-msvideo" + extension: ".avi" }, { name: "WMV", - extension: ".wmv", - mimeType: "video/x-ms-asf" + extension: ".wmv" }, { name: "MP3", - extension: ".mp3", - mimeType: "audio/mp4" + extension: ".mp3" } ] diff --git a/src/model/format.ts b/src/model/format.ts index 276ec6e..c98ca74 100644 --- a/src/model/format.ts +++ b/src/model/format.ts @@ -4,6 +4,4 @@ export type Format = { name: string /** Extension with a dot */ extension: string - /** Mime type of this format, that allow it to be downloaded */ - mimeType: string } \ No newline at end of file diff --git a/src/services/converter.ts b/src/services/converter.ts index 42d1112..4c6cd22 100644 --- a/src/services/converter.ts +++ b/src/services/converter.ts @@ -2,6 +2,14 @@ import { createFFmpeg } from "@ffmpeg/ffmpeg"; import { UploadFile } from "antd"; import { ConvertedFile } from "../model/converted-file"; +const mimeType = { + ".gif": "image/gif", + ".mp4": "video/mp4", + ".avi": "video/x-msvideo", + ".wmv": "video/x-ms-wmv", + ".mp3": "audio/mp3", +} + async function convertFiles(fileList: UploadFile[], extension: string): Promise{ const blobList: ConvertedFile[] = [] @@ -23,12 +31,21 @@ async function convertFiles(fileList: UploadFile[], extension: string): Promise< await ffmpeg.run("-i", file.name, outputName); const output = ffmpeg.FS("readFile", outputName); - const blob = new Blob([output.buffer], { type: "image/gif" }) - blobList.push({ - newFileName: outputName, - blob, - result: "success" - }) + + if (output === null || output.buffer.byteLength <= 0 ) { + blobList.push({ + newFileName: outputName, + result: "error", + blob: new Blob() + }) + } else { + const blob = new Blob([output.buffer], { type: mimeType[extension as keyof typeof mimeType] }) + blobList.push({ + newFileName: outputName, + blob, + result: "success" + }) + } } return blobList