From 2b3473c0ffe6ea1aa88422ee10f16c17ec4234bd Mon Sep 17 00:00:00 2001 From: Chetan baliyan Date: Tue, 15 Aug 2023 23:30:17 +0530 Subject: [PATCH] feat : add function to download and add image in video --- src/images/downloadImages.ts | 17 +++++++ src/images/imagesProccessing.ts | 81 ++++++++------------------------- src/index.ts | 58 +++++++++++++++++------ src/promptTemplates/image.ts | 4 +- 4 files changed, 82 insertions(+), 78 deletions(-) create mode 100644 src/images/downloadImages.ts diff --git a/src/images/downloadImages.ts b/src/images/downloadImages.ts new file mode 100644 index 0000000..e6a8e1e --- /dev/null +++ b/src/images/downloadImages.ts @@ -0,0 +1,17 @@ +import axios from 'axios' +import fs from 'fs' +export const downloadImages = async (queries: any) => { + for (const query of queries) { + const name = query.timestamp.split('->')[0].trim() + const { data } = await axios.get(`https://api.unsplash.com/search/photos?query=${query.Query}&page=1`, { + headers: { + Authorization: `Client-ID ${process.env.UNSPLASH_ACCESS_KEY}`, + }, + }) + const url = data.results[0].urls.thumb + const response = await axios.get(url, { + responseType: 'stream', + }) + await response.data.pipe(fs.createWriteStream(`${name}.jpg`)) + } +} diff --git a/src/images/imagesProccessing.ts b/src/images/imagesProccessing.ts index cc943fc..db2f2f8 100644 --- a/src/images/imagesProccessing.ts +++ b/src/images/imagesProccessing.ts @@ -16,26 +16,26 @@ const configuration = new Configuration({ }) const openai = new OpenAIApi(configuration) -export const imageProccessing = async ({ language, topic }: { language?: string; topic?: string }) => { +export const imageProccessing = async ({ + language, + topic, + queries, +}: { + language?: string + topic?: string + queries: any +}) => { const inputVideoPath = '/home/chetan/code/ts-content-gpt/tryyyyyyyyy.mp4' const inputImagePath = '/home/chetan/code/ts-content-gpt/oo.jpg' const outputVideoPath = '/home/chetan/code/ts-content-gpt/yyooooooo.mp4' const targetTimestamp = '00:00:10.000' - const queries = [ - { Query: 'Great Wall of China', timestamp: '1 -> 3' }, - { Query: 'longest wall in the world', timestamp: '5 -> 8' }, - // { Query: 'Ming Dynasty', timestamp: '7 -> 8' }, - // { Query: 'Chinese Empire', timestamp: '11 -> 12' }, - // { Query: 'brick, tamperth, and stone', timestamp: '17 -> 18' }, - ] - interface IQuery { Query: string timestamp: string } let filter = '' - queries.forEach((query: IQuery, index) => { + queries.forEach((query: IQuery, index: any) => { const currIndex = index + 1 const prevIndex = index const totalQuery = queries.length @@ -43,7 +43,13 @@ export const imageProccessing = async ({ language, topic }: { language?: string; const [startingTime, endTime] = query.timestamp.split('->') if (index === 0) { - filter += ` -filter_complex "[${prevIndex}:v][${currIndex}:v]overlay=25:25:enable='between(t,${startingTime.trim()},${endTime.trim()})'[v${currIndex}];[v${currIndex}]` + let imgPath = '' + + queries.forEach((query: IQuery, index: any) => { + imgPath += ' -i ' + `/home/chetan/code/ts-content-gpt/${query.timestamp.split('->')[0].trim()}.jpg` + }) + + filter += `${imgPath} -filter_complex "[${prevIndex}:v][${currIndex}:v]overlay=25:25:enable='between(t,${startingTime.trim()},${endTime.trim()})'[v${currIndex}];[v${currIndex}]` return } @@ -58,20 +64,10 @@ export const imageProccessing = async ({ language, topic }: { language?: string; // console.log('filter: ', filter) - const mainFilter = `${path} -i ${inputVideoPath} -i ${inputImagePath} -i ${inputImagePath} ${filter} -map "[v]" -map 0:a -c:v libx264 -c:a copy ${outputVideoPath} ` + const mainFilter = `${path} -i ${inputVideoPath} ${filter} -map "[v]" -map 0:a -c:v libx264 -c:a copy ${outputVideoPath} ` console.log('mainFilter: ', mainFilter) - const ll = `${path} -i ${inputVideoPath} -i ${inputVideoPath} -i ${inputImagePath} -filter_complex "[0:v][1:v]overlay=25:25:enable='between(t,1 , 2)'[v1];[v1][2:v]overlay=25:25:enable='between(t,3 , 4)'[v2];[v2]format=yuv420p[v]" -map "[v]" -map 0:a -c:v libx264 -c:a copy /home/chetan/code/ts-content-gpt/yyooooooo.mp4` - - // const command = `${path} -i ${inputVideoPath} -i ${inputImagePath} -filter_complex "[0:v][1:v] overlay=25:25:enable='between(t,0,10)'" -pix_fmt yuv420p -c:a copy ${outputVideoPath}` - // const command = `${path} -i ${inputVideoPath} -i ${inputImagePath} -filter_complex "[1:v]scale=-1:100[ovrl];[0:v][ovrl]overlay=x=W-w-10:y=10:enable='between(t,${targetTimestamp},T)'[out]" -map "[out]" -map 0:a -c:v libx264 -c:a copy ${outputVideoPath}` - // const i = `[0:v][1:v]overlay=25:25:enable='between(t,1 , 2)'[v1]; [v1][2:v]overlay=25:25:enable='between(t,3 , 4)'[v2]; [v2]format=yuv420p[v]" -map "[v]" -map 0:a -c:v libx264 -c:a copy /home/chetan/code/ts-content-gpt/yyooooooo.mp4` - // const command = `${path} -i ${inputVideoPath} -i ${inputImagePath} -i ${inputImagePath} -filter_complex "[0:v][1:v]overlay=25:25:enable='between(t,0,10)'[v1]; [v1][2:v]overlay=50:50:enable='between(t,15,20)'[v2]; [v2]format=yuv420p[v]" -map "[v]" -map 0:a -c:v libx264 -c:a copy ${outputVideoPath}` - // const command = `${path} -i ${inputVideoPath} -i ${inputImagePath} -i ${inputImagePath} -i ${inputImagePath} -filter_complex " [0:v][1:v]overlay=25:25:enable='between(t,0,10)'[v1];[v1] [2:v]overlay=50:50:enable='between(t,13,20)'[v2]; [v2][3:v]overlay=75:75:enable='between(t,23,30)'[v3]; [v3]format=yuv420p[v]" -map "[v]" -map 0:a -c:v libx264 -c:a copy ${outputVideoPath}` - - // const command = `${path} -i ${inputVideoPath} -i ${inputImagePath} -i ${inputImagePath} -i ${inputImagePath} -i ${inputImagePath} -i ${inputImagePath} -filter_complex "[0:v][1:v]overlay=25:25:enable='between(t,0,5)'[v1];[v1][2:v]overlay=50:50:enable='between(t,7,13)'[v2];[v2][3:v]overlay=75:75:enable='between(t,12,16)'[v3];[v3][4:v]overlay=100:100:enable='between(t,18,22)'[v4];[v4][5:v]overlay=125:125:enable='between(t,24,26)'[v5];[v5]format=yuv420p[v]" -map "[v]" -map 0:a -c:v libx264 -c:a copy ${outputVideoPath}` - exec(mainFilter, (err, stdout, stderr) => { if (err) { console.error(err) @@ -79,45 +75,4 @@ export const imageProccessing = async ({ language, topic }: { language?: string; } // console.log(stdout) }) - - return - ffmpeg() - .input(inputVideoPath) - .input(inputImagePath) - .complexFilter([ - { - filter: 'setpts', - options: `PTS-STARTPTS+(gte(T,${targetTimestamp})*(${targetTimestamp}-PTS/TB))`, - outputs: 'timestamped', - }, - { - filter: 'overlay', - options: { - x: 'W-w-10', - y: '10', - }, - inputs: ['timestamped', '1'], // Use the 'timestamped' output from the previous filter and the image input - outputs: 'out', - }, - ]) - .outputOptions('-map', '[out]') - .outputOptions('-c:v', 'libx264') - .output(outputVideoPath) - .on('end', () => { - console.log('Image overlay complete!') - }) - .on('error', err => { - console.error(err) - }) - .run() - - return - fs.readFile('/home/chetan/code/ts-content-gpt/basicaudio.wav.srt', 'utf8', async function (err, data) { - if (err) throw err - const chatCompletion = await openai.createChatCompletion({ - model: 'gpt-3.5-turbo', - messages: [{ role: 'system', content: tryy(data) }], - }) - console.log('chatCompletion: ', chatCompletion.data.choices[0].message) - }) } diff --git a/src/index.ts b/src/index.ts index ed25766..a463598 100644 --- a/src/index.ts +++ b/src/index.ts @@ -13,6 +13,8 @@ import { mergeAudio } from './video/video' import { uploadVideos } from './upoad/upload' import uploadFile from './upoad/azureUpload' import { imageProccessing } from './images/imagesProccessing' +import { downloadImages } from './images/downloadImages' +import { getImageQuerys } from './Editing/getImageQuerys' const inputFilePath = path.join(__dirname, '..', 'basicaudio.mp3') const outputFilePath = path.join(__dirname, '..', 'basicaudio.wav') @@ -23,27 +25,36 @@ const outputVideoFilePath = path.join(__dirname, '..', 'shorts', 'ytshort.mp4') const generateYoutubeShort = async (language: string, topic: string) => { try { - const script = await createShortScript({ language: language, topic: topic }) + // const script = await createShortScript({ language: language, topic: topic }) - console.log('SCRIPT GENERATED: ', script) + // console.log('SCRIPT GENERATED: ', script) - if (!script) throw new Error('Script not generated') + // if (!script) throw new Error('Script not generated') - await createAudio({ script, language, outputFilePath: inputFilePath }) + // await createAudio({ script, language, outputFilePath: inputFilePath }) - console.log('AUDIO GENERATED SUCCESSFULLY', 'basicaudio.mp3') + // console.log('AUDIO GENERATED SUCCESSFULLY', 'basicaudio.mp3') - await convertToWav(inputFilePath, outputFilePath) + // await convertToWav(inputFilePath, outputFilePath) - await whisper(outputFilePath) + // await whisper(outputFilePath) - console.log('MERGING AUDIO AND VIDEO') + // console.log('MERGING AUDIO AND VIDEO') + + // await mergeAudio({ + // videoFilePath, + // audioFilePath: outputFilePath, + // outputVideoPath: outputVideoFilePath, + // }) + + const queries = await getImageQuerys() + + console.log('QUERIES: ', queries) + + await downloadImages(queries) + + await imageProccessing({ language: '', queries }) - await mergeAudio({ - videoFilePath, - audioFilePath: outputFilePath, - outputVideoPath: outputVideoFilePath, - }) return // uploadVideos('facts', 'facts', ['#facts', '#trending', '#shorts'], outputVideoFilePath) uploadFile('videos', Math.random() + 'new.mp4', outputVideoFilePath).catch(console.error) @@ -60,7 +71,26 @@ const generateYoutubeShort = async (language: string, topic: string) => { // app.use(express.json()) -imageProccessing({ language: '' }) +generateYoutubeShort('english', 'indian fact') + +const queries = [ + { Query: 'Great Wall of China', timestamp: '1 -> 3' }, + { Query: 'Chinese Empire', timestamp: '11 -> 12' }, + // { Query: 'Ming Dynasty', timestamp: '7 -> 8' }, + // { Query: 'Chinese Empire', timestamp: '11 -> 12' }, + // { Query: 'brick, tamperth, and stone', timestamp: '17 -> 18' }, +] + +// mergeAudio({ +// videoFilePath, +// audioFilePath: outputFilePath, +// outputVideoPath: outputVideoFilePath, +// }) + +// imageProccessing({ language: '', queries }) + +// downloadImages(queries) + // app.post('/generate', async (req, res) => { // try { // const { language, topic } = req.body diff --git a/src/promptTemplates/image.ts b/src/promptTemplates/image.ts index 32a256f..ef5a652 100644 --- a/src/promptTemplates/image.ts +++ b/src/promptTemplates/image.ts @@ -32,10 +32,12 @@ export const tryy = ( timestamp: string ) => `this is a timestamp for my video , i am using a api to fetch images , so based on this given timetamp you have to give me 5 best query by which i can fetch images also you have to send on what time i have to show that image , Time is in formet of hh:mm:ss,ms --> hh:mm:ss,ms , so you only have to return seconds part of timestamp , for example if timestamp is 00:00:10,000 --> 00:00:15,000 , you only have to return 10 -> 15 , so i can show image between 10 to 15 seconds of video - +Make sure that you only return good querys , so that it will be easy to find image for that specifications delimited by angle brackets . TIMESTAMP: <${timestamp}> ### OUTPUT +You will output in parsable JSON object , all these json will be in a array. +make sure to return only seconds in timestamp like 5 -> 10 ,24 -> 30 etc [{"Query":"...","timestamp":".. -> .."}]`