From 156222f28c42b332941af6dd8deceab1cb103787 Mon Sep 17 00:00:00 2001 From: an-lee Date: Mon, 13 May 2024 10:25:28 +0800 Subject: [PATCH] Feat: may download segment (#601) * may download segment audio * display original audio with the recording in post --- enjoy/src/api/client.ts | 15 +++ enjoy/src/i18n/en.json | 1 + enjoy/src/i18n/zh-CN.json | 1 + enjoy/src/main/db/handlers/audios-handler.ts | 20 ++++ enjoy/src/main/db/handlers/videos-handler.ts | 20 ++++ enjoy/src/main/db/models/audio.ts | 18 +++ enjoy/src/main/db/models/video.ts | 18 +++ enjoy/src/preload.ts | 6 + .../components/medias/media-caption.tsx | 104 +++++++++++++++++- .../medias/media-current-recording.tsx | 12 ++ .../components/medias/media-recorder.tsx | 5 + .../components/posts/post-recording.tsx | 28 ++++- .../context/media-player-provider.tsx | 2 +- enjoy/src/renderer/hooks/use-segments.tsx | 3 +- enjoy/src/types/enjoy-app.d.ts | 8 ++ enjoy/src/types/segment.d.ts | 2 + 16 files changed, 258 insertions(+), 5 deletions(-) diff --git a/enjoy/src/api/client.ts b/enjoy/src/api/client.ts index 5170106f..8b67c6e3 100644 --- a/enjoy/src/api/client.ts +++ b/enjoy/src/api/client.ts @@ -440,4 +440,19 @@ export class Client { payment(id: string): Promise { return this.api.get(`/api/payments/${id}`); } + + mineSegments(params?: { + page?: number; + segmentIndex?: number; + targetId?: string; + targetType?: string; + }): Promise< + { + segments: SegmentType[]; + } & PagyResponseType + > { + return this.api.get("/api/mine/segments", { + params: decamelizeKeys(params), + }); + } } diff --git a/enjoy/src/i18n/en.json b/enjoy/src/i18n/en.json index d4fe10da..36d5f560 100644 --- a/enjoy/src/i18n/en.json +++ b/enjoy/src/i18n/en.json @@ -168,6 +168,7 @@ "translate": "translate", "displayIpa": "display IPA", "displayNotes": "display Notes", + "downloadSegment": "download segment", "detail": "detail", "remove": "remove", "share": "share", diff --git a/enjoy/src/i18n/zh-CN.json b/enjoy/src/i18n/zh-CN.json index 9ed2f92b..ef6c2120 100644 --- a/enjoy/src/i18n/zh-CN.json +++ b/enjoy/src/i18n/zh-CN.json @@ -168,6 +168,7 @@ "translate": "翻译", "displayIpa": "标注音标", "displayNotes": "显示笔记", + "downloadSegment": "下载选段", "detail": "详情", "remove": "删除", "share": "分享", diff --git a/enjoy/src/main/db/handlers/audios-handler.ts b/enjoy/src/main/db/handlers/audios-handler.ts index 086c1794..e5060c54 100644 --- a/enjoy/src/main/db/handlers/audios-handler.ts +++ b/enjoy/src/main/db/handlers/audios-handler.ts @@ -5,6 +5,7 @@ import downloader from "@main/downloader"; import log from "@main/logger"; import { t } from "i18next"; import youtubedr from "@main/youtubedr"; +import { pathToEnjoyUrl } from "@/main/utils"; const logger = log.scope("db/handlers/audios-handler"); @@ -187,6 +188,24 @@ class AudiosHandler { }); } + private async crop( + _event: IpcMainEvent, + id: string, + params: { startTime: number; endTime: number } + ) { + const audio = await Audio.findOne({ + where: { id }, + }); + if (!audio) { + throw new Error(t("models.audio.notFound")); + } + + const { startTime, endTime } = params; + const output = await audio.crop({ startTime, endTime }); + + return pathToEnjoyUrl(output); + } + register() { ipcMain.handle("audios-find-all", this.findAll); ipcMain.handle("audios-find-one", this.findOne); @@ -194,6 +213,7 @@ class AudiosHandler { ipcMain.handle("audios-update", this.update); ipcMain.handle("audios-destroy", this.destroy); ipcMain.handle("audios-upload", this.upload); + ipcMain.handle("audios-crop", this.crop); } } diff --git a/enjoy/src/main/db/handlers/videos-handler.ts b/enjoy/src/main/db/handlers/videos-handler.ts index d6f9707f..82c9a16d 100644 --- a/enjoy/src/main/db/handlers/videos-handler.ts +++ b/enjoy/src/main/db/handlers/videos-handler.ts @@ -5,6 +5,7 @@ import downloader from "@main/downloader"; import log from "@main/logger"; import { t } from "i18next"; import youtubedr from "@main/youtubedr"; +import { pathToEnjoyUrl } from "@main/utils"; const logger = log.scope("db/handlers/videos-handler"); @@ -173,6 +174,24 @@ class VideosHandler { }); } + private async crop( + _event: IpcMainEvent, + id: string, + params: { startTime: number; endTime: number } + ) { + const video = await Video.findOne({ + where: { id }, + }); + if (!video) { + throw new Error(t("models.video.notFound")); + } + + const { startTime, endTime } = params; + const output = await video.crop({ startTime, endTime }); + + return pathToEnjoyUrl(output); + } + register() { ipcMain.handle("videos-find-all", this.findAll); ipcMain.handle("videos-find-one", this.findOne); @@ -180,6 +199,7 @@ class VideosHandler { ipcMain.handle("videos-update", this.update); ipcMain.handle("videos-destroy", this.destroy); ipcMain.handle("videos-upload", this.upload); + ipcMain.handle("videos-crop", this.crop); } } diff --git a/enjoy/src/main/db/models/audio.ts b/enjoy/src/main/db/models/audio.ts index 219e204a..d456ee18 100644 --- a/enjoy/src/main/db/models/audio.ts +++ b/enjoy/src/main/db/models/audio.ts @@ -28,6 +28,7 @@ import Ffmpeg from "@main/ffmpeg"; import { Client } from "@/api"; import startCase from "lodash/startCase"; import { v5 as uuidv5 } from "uuid"; +import FfmpegWrapper from "@main/ffmpeg"; const SIZE_LIMIT = 1024 * 1024 * 50; // 50MB @@ -189,6 +190,23 @@ export class Audio extends Model