11import * as log from "@std/log" ;
22import process from "node:process" ;
3- import childProcess from "node:child_process" ;
43import { z } from "zod" ;
54import * as path from "@std/path" ;
65import { createHash } from "node:crypto" ;
@@ -107,8 +106,7 @@ export function getFrontendDir(): string {
107106}
108107
109108export function start ( path : string ) {
110- const escapedPath = escapeString ( path ) ;
111- childProcess . exec ( `start "" ${ escapedPath } ` ) ;
109+ Deno . spawn ( "cmd" , [ "/c" , "start" , "" , path ] ) ;
112110}
113111
114112export function isDev ( ) {
@@ -181,23 +179,19 @@ export function getShortHash(bytes: Uint8Array): string {
181179}
182180
183181export async function getVideoInfo ( videoPath : string ) : Promise < VideoInfo > {
184- // ffprobe -v error -select_streams v:0 -show_entries stream=codec_name,width,height,duration -of json input_video.mp4
185- const command = new Deno . Command ( ffprobe , {
186- args : [
187- "-v" ,
188- "error" ,
189- "-select_streams" ,
190- "v:0" ,
191- "-show_entries" ,
192- "stream=codec_name,width,height" ,
193- "-show_entries" ,
194- "format=duration" ,
195- "-of" ,
196- "json" ,
197- videoPath ,
198- ] ,
199- } ) ;
200- const output = await command . output ( ) ;
182+ const output = await Deno . spawnAndWait ( ffprobe , [
183+ "-v" ,
184+ "error" ,
185+ "-select_streams" ,
186+ "v:0" ,
187+ "-show_entries" ,
188+ "stream=codec_name,width,height" ,
189+ "-show_entries" ,
190+ "format=duration" ,
191+ "-of" ,
192+ "json" ,
193+ videoPath ,
194+ ] ) ;
201195 if ( output . code !== 0 ) {
202196 const errorMsg = new TextDecoder ( ) . decode ( output . stderr ) ;
203197 throw new Error ( `Error executing ffprobe: ${ errorMsg } , ${ output . code } ` ) ;
@@ -220,18 +214,15 @@ export async function getVideoInfo(videoPath: string): Promise<VideoInfo> {
220214}
221215
222216export async function generateThumbnail ( videoPath : string , thumbnailPath : string ) {
223- let command = new Deno . Command ( ffprobe , {
224- args : [
225- "-v" ,
226- "error" ,
227- "-show_entries" ,
228- "format=duration" ,
229- "-of" ,
230- "default=noprint_wrappers=1:nokey=1" ,
231- videoPath ,
232- ] ,
233- } ) ;
234- let output = await command . output ( ) ;
217+ let output = await Deno . spawnAndWait ( ffprobe , [
218+ "-v" ,
219+ "error" ,
220+ "-show_entries" ,
221+ "format=duration" ,
222+ "-of" ,
223+ "default=noprint_wrappers=1:nokey=1" ,
224+ videoPath ,
225+ ] ) ;
235226
236227 if ( output . code !== 0 ) {
237228 const errorMsg = new TextDecoder ( ) . decode ( output . stderr ) ;
@@ -248,25 +239,23 @@ export async function generateThumbnail(videoPath: string, thumbnailPath: string
248239
249240 const targetWidth = 512 ;
250241
251- command = new Deno . Command ( ffmpeg , {
252- args : [
253- "-ss" ,
254- target + "" ,
255- "-i" ,
256- videoPath ,
257- "-vf" ,
258- // Generate thumbnail's width is always fixed
259- // SAR = Storage Aspect Ratio, some videos let's say original resolution is 1440x1080, but the video is 16:9, so the SAR is 1.3333
260- // Width: 512px
261- // Height Formula = Height * (512 / Width) * (1 / SAR)
262- `scale=${ targetWidth } :ih*(1/sar)*(${ targetWidth } /iw)` ,
263- "-vframes" ,
264- "1" ,
265- thumbnailPath ,
266- ] ,
242+ output = await Deno . spawnAndWait ( ffmpeg , [
243+ "-ss" ,
244+ target + "" ,
245+ "-i" ,
246+ videoPath ,
247+ "-vf" ,
248+ // Generate thumbnail's width is always fixed
249+ // SAR = Storage Aspect Ratio, some videos let's say original resolution is 1440x1080, but the video is 16:9, so the SAR is 1.3333
250+ // Width: 512px
251+ // Height Formula = Height * (512 / Width) * (1 / SAR)
252+ `scale=${ targetWidth } :ih*(1/sar)*(${ targetWidth } /iw)` ,
253+ "-vframes" ,
254+ "1" ,
255+ thumbnailPath ,
256+ ] , {
267257 stdout : "piped" ,
268258 } ) ;
269- output = await command . output ( ) ;
270259
271260 if ( output . code !== 0 ) {
272261 log . error ( "Error executing ffmpeg:" , output . stderr ) ;
0 commit comments