@@ -1,4 +1,4 @@ | |||||
import * as childProcess from 'child_process'; | |||||
import { spawnSync } from 'child_process'; | |||||
import { unlinkSync, readFileSync } from 'fs'; | import { unlinkSync, readFileSync } from 'fs'; | ||||
export enum VideoType { | export enum VideoType { | ||||
@@ -9,7 +9,6 @@ interface ClipVideoBaseParams { | |||||
url: string, | url: string, | ||||
start: number | string, | start: number | string, | ||||
end: number | string, | end: number | string, | ||||
ffmpegExecutablePath?: string; | |||||
} | } | ||||
interface ClipYouTubeVideoParams extends ClipVideoBaseParams { | interface ClipYouTubeVideoParams extends ClipVideoBaseParams { | ||||
@@ -24,12 +23,16 @@ const clipYouTubeVideo = (params: ClipYouTubeVideoParams) => { | |||||
if (!params.downloaderExecutablePath) { | if (!params.downloaderExecutablePath) { | ||||
throw new Error('Downloader not found.'); | throw new Error('Downloader not found.'); | ||||
} | } | ||||
if (!params.ffmpegExecutablePath) { | |||||
throw new Error('ffmpeg not found.'); | |||||
} | |||||
childProcess.spawnSync(params.downloaderExecutablePath, [params.url, '-o', 'input.webm']); | |||||
childProcess.spawnSync(params.ffmpegExecutablePath, ['-ss', params.start.toString(), '-t', params.end.toString(), '-i', 'input.webm', 'output.webm']); | |||||
unlinkSync('input.webm'); | |||||
spawnSync( | |||||
params.downloaderExecutablePath, | |||||
[ | |||||
'--postprocessor-args', | |||||
`-ss ${params.start.toString()} -to ${params.end.toString()}`, | |||||
'-o', | |||||
'output.webm', | |||||
params.url, | |||||
], | |||||
); | |||||
const output = readFileSync('output.webm'); | const output = readFileSync('output.webm'); | ||||
unlinkSync('output.webm'); | unlinkSync('output.webm'); | ||||
return output; | return output; | ||||
@@ -38,13 +41,13 @@ const clipYouTubeVideo = (params: ClipYouTubeVideoParams) => { | |||||
export const clipVideo = (params: ClipVideoParams) => { | export const clipVideo = (params: ClipVideoParams) => { | ||||
const { | const { | ||||
type: videoType, url, start, end, | type: videoType, url, start, end, | ||||
downloaderExecutablePath, | |||||
} = params; | } = params; | ||||
switch (videoType as string) { | switch (videoType as string) { | ||||
case VideoType.YOUTUBE: | case VideoType.YOUTUBE: | ||||
return clipYouTubeVideo({ | return clipYouTubeVideo({ | ||||
ffmpegExecutablePath: process.env.FFMPEG_EXECUTABLE_PATH, | |||||
downloaderExecutablePath: process.env.YOUTUBE_DOWNLOADER_EXECUTABLE_PATH, | |||||
downloaderExecutablePath, | |||||
url, | url, | ||||
start, | start, | ||||
end, | end, | ||||
@@ -1,22 +1,57 @@ | |||||
import { | import { | ||||
describe, it, expect, vi, | |||||
describe, it, expect, vi, beforeEach, Mock, | |||||
} from 'vitest'; | } from 'vitest'; | ||||
import * as childProcess from 'child_process'; | |||||
import { spawnSync } from 'child_process'; | |||||
import { readFileSync, unlinkSync } from 'fs'; | |||||
import * as youtubeClipCore from '../src'; | import * as youtubeClipCore from '../src'; | ||||
vi.mock('child_process', () => ({ | vi.mock('child_process', () => ({ | ||||
spawnSync: vi.fn(), | spawnSync: vi.fn(), | ||||
})); | })); | ||||
vi.mock('fs', () => ({ | |||||
readFileSync: vi.fn(), | |||||
unlinkSync: vi.fn(), | |||||
})); | |||||
describe('clipVideo', () => { | describe('clipVideo', () => { | ||||
it('works', () => { | |||||
beforeEach(() => { | |||||
(readFileSync as Mock).mockReturnValueOnce(Buffer.from('')); | |||||
}); | |||||
it('calls the downloader function', () => { | |||||
youtubeClipCore.clipVideo({ | |||||
downloaderExecutablePath: 'yt-dlp', | |||||
type: youtubeClipCore.VideoType.YOUTUBE, | |||||
url: 'https://www.youtube.com/watch?v=BaW_jenozKc', | |||||
start: 0, | |||||
end: 0, | |||||
}); | |||||
expect(spawnSync).toBeCalledWith('yt-dlp', expect.anything()); | |||||
}); | |||||
it('calls the buffer extract function', () => { | |||||
youtubeClipCore.clipVideo({ | |||||
downloaderExecutablePath: 'yt-dlp', | |||||
type: youtubeClipCore.VideoType.YOUTUBE, | |||||
url: 'https://www.youtube.com/watch?v=BaW_jenozKc', | |||||
start: 0, | |||||
end: 0, | |||||
}); | |||||
expect(readFileSync).toBeCalled(); | |||||
}); | |||||
it('calls the cleanup function', () => { | |||||
youtubeClipCore.clipVideo({ | youtubeClipCore.clipVideo({ | ||||
downloaderExecutablePath: 'yt-dlp', | |||||
type: youtubeClipCore.VideoType.YOUTUBE, | type: youtubeClipCore.VideoType.YOUTUBE, | ||||
url: 'https://www.youtube.com/watch?v=BaW_jenozKc', | url: 'https://www.youtube.com/watch?v=BaW_jenozKc', | ||||
start: 0, | start: 0, | ||||
end: 0, | end: 0, | ||||
}); | }); | ||||
expect(childProcess.spawnSync).toBeCalledTimes(2); | |||||
expect(unlinkSync).toBeCalled(); | |||||
}); | }); | ||||
}); | }); |
@@ -1,7 +1,11 @@ | |||||
const { clipVideo, VideoType } = require('../dist/cjs/development'); | const { clipVideo, VideoType } = require('../dist/cjs/development'); | ||||
const fs = require('fs'); | const fs = require('fs'); | ||||
const dotenv = require('dotenv'); | |||||
dotenv.config(); | |||||
const clippedVideoBuffer = clipVideo({ | const clippedVideoBuffer = clipVideo({ | ||||
downloaderExecutablePath: process.env.YOUTUBE_DOWNLOADER_EXECUTABLE_PATH, | |||||
type: VideoType.YOUTUBE, | type: VideoType.YOUTUBE, | ||||
url: 'https://www.youtube.com/watch?v=BaW_jenozKc', | url: 'https://www.youtube.com/watch?v=BaW_jenozKc', | ||||
start: 0, | start: 0, | ||||