Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
/index.ts
.env
.idea
node_modules
Expand Down
8 changes: 4 additions & 4 deletions combineStream.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import fs from 'fs';
import ffmpeg from "fluent-ffmpeg";

const combinedStreams = (dir, latestFile, feature) => {
const combinedStreams = (dir, latestFile, feature, numberOfFiles) => {
return new Promise((resolve, reject) => {
let files = []
fs.readdirSync(`${dir}`).forEach(file => {
files.push(`${dir}/${file}`)
});
for(let i = 0; i < numberOfFiles; i++) {
files.push(`${dir}/${i}.mp3`)
}
const combiner = ffmpeg().on("error", err => {
console.error("An error occurred: " + err.message);
})
Expand Down
16 changes: 3 additions & 13 deletions cypress/integration/getVideoUrls/getVideos.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,10 @@ describe('Get Video', () => {
})

it('get this ', () => {
const feature = 5;
// const e = fs.readFileSync(`./curated-list/${feature}/1.txt`)
// console.log(e.toString().split("\n"));

cy.readFile(`./curated-list/${feature}/1.txt`).then((fileUrl) => {
cy.readFile(`./curated-list/${Cypress.env('fileUpto')}/1.txt`).then((fileUrl) => {
const c = fileUrl.split('\n')
// read in file list and write next file name as file i.e. 1, 2, 3... etc.
c.forEach((item) => {
Expand All @@ -35,23 +34,14 @@ describe('Get Video', () => {
console.log('below')
console.log(updatedUrl.redirects.toString().split(' ')[1]);
console.log('above')
cy.writeFile('./random-video-links/te.txt', updatedUrl.redirects.toString().split(' ')[1] + ',' + item.split(',')[1] + '\n', { flag: 'a+', timeout: 30000 });
cy.writeFile(`./random-video-links/${Cypress.env('fileUpto')}/1.txt`, updatedUrl.redirects.toString().split(' ')[1] + ',' + item.split(',')[1] + '\n', { flag: 'a+', timeout: 120000 });
})
}
})
// cy.request({
// url: fileUrl,
// method: 'GET'
// }).then((updatedUrl) => {
// console.log('below')
// console.log(updatedUrl.redirects.toString().split(' '));
// console.log('above')
// cy.writeFile('./random-video-links/te.txt', updatedUrl.redirects.toString().split(' ')[1]);
// })
})
})
after(() => {
// pass duration here.
cy.exec(`ts-node generateTemplates.ts ${Cypress.env('duration')}`)
cy.exec(`ts-node generateTemplates.ts ${Cypress.env('duration')}`, { timeout: 120000 })
})
})
43 changes: 32 additions & 11 deletions enoughVideos.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,43 @@ import randomWords from "random-words";
const getRandomInt = (max) => {
return Math.floor(Math.random() * max);
}

let listVids = [];
const enoughVideos = async (listVideos, durationOfAudio) => {
let newList = listVideos;
const t = await getVideo(randomWords())
const duration = newList.reduce((currentValue, previousValue) => ({duration: currentValue.duration + previousValue.duration}));
if(duration.duration > durationOfAudio) {
if((duration.duration - durationOfAudio) < 40) {
return newList
if(listVideos) {
let newList = listVideos;
if(t !== undefined) {
listVids = [...listVideos, ...t];
} else {
const y = await getVideo(randomWords())
enoughVideos(y, durationOfAudio)
}


console.log(listVids)
const duration = listVids.reduce((currentValue, previousValue) => ({duration: currentValue?.duration + previousValue?.duration}), {duration: 0});
console.log('below')
console.log(duration.duration)
console.log(durationOfAudio);
console.log('above')

if(duration.duration > durationOfAudio) {
if((duration.duration - durationOfAudio) < 220) {
return listVids
}
listVids.pop();
return enoughVideos(newList, durationOfAudio);
}
newList.pop();
return enoughVideos(newList, durationOfAudio);
const c = [t[getRandomInt(t.length)], ...newList]
listVids = [...listVideos, ...c];
// this is where we can do a call to get more video.
return enoughVideos(c, durationOfAudio);
} else {
const t = await getVideo(randomWords())
listVids = [...listVideos, ...t];
enoughVideos(t, durationOfAudio);
}
const c = [t[getRandomInt(t.length)], ...newList]

// this is where we can do a call to get more video.
return enoughVideos(c, durationOfAudio);
}

export default enoughVideos;
6 changes: 5 additions & 1 deletion generateTemplates.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,17 @@ class GenerateTemplates {
return parseInt(process.argv.slice(2).toString(), 10);
}

public getLinksFolder(): number {
return fs.readdirSync('./random-video-links').length;
}

public generateCompositionTemplate(){
const compositionTemplate = CompositionTemplateFile(this.getDuration());
fs.writeFileSync('./output-video-template/composition-files.tsx', compositionTemplate);
}

public generateVideoTemplate() {
const procesedVideoLinks = fs.readFileSync('./random-video-links/te.txt')
const procesedVideoLinks = fs.readFileSync(`./random-video-links/${this.getLinksFolder()}/1.txt`)
let vidTemplates = [];

procesedVideoLinks.toString().split('\n').forEach((line) => {
Expand Down
2 changes: 1 addition & 1 deletion generateTextFile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ export default class GenerateTextFile {

public splitTextFile(): string[] {
const str = fs.readFileSync(`./whole-story-text/${this.getLatestStory()}/1.txt`);
return this.yourSplit(10, str.toString().replace(/\'/g, ''))
return this.yourSplit(4, str.toString().replace(/\'/g, ''))
}

public getLatestStory(): number {
Expand Down
6 changes: 5 additions & 1 deletion getStory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,13 @@ const getStory = async (directory, fileName, wholeStoryNumber) => {
const post = await getPost('AmItheAsshole');
return new Promise((resolve, reject) => {
const gtts = new gTTS(post['selftext'], 'en');
console.log('below is file name')
console.log(fileName)
console.log(wholeStoryNumber)
console.log('above is file name')
// we write each post to its own directory AND append to the same file
// because gtts could be run on separate threads... so future proofing parallel processing speed.
fs.writeFileSync(`./story-text/${directory}/${fileName}.txt`, post['selftext'].replace(/\n/g, ''));
// fs.writeFileSync(`./story-text/${directory}/${fileName}.txt`, post['selftext'].replace(/\n/g, ''));
fs.writeFileSync(`./whole-story-text/${wholeStoryNumber}/1.txt`, post['selftext'].replace(/\n/g, ''), {flag: 'a+'} )
gtts.save(`./stories/${directory}/${fileName}.mp3`, function (err, result) {
if (err) {
Expand Down
1 change: 1 addition & 0 deletions getVideo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import axios from 'axios';

const getVideo = async (videoName) => {
console.log('search term:::-', videoName);
// handle the undefined results here.. recursively poll until returning something.
const req = await axios.get(`https://pixabay.com/api/videos/?key=21063902-7eaa7556445c3e0dd44c20488&q=${videoName}`)
if (req.data.hits){
return req.data.hits
Expand Down
119 changes: 119 additions & 0 deletions index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
import randomWords from "random-words";
import getVideo from "./getVideo";
import organiseVideoByRating from "./organiseVideo";
import enoughVideos from './enoughVideos';
import getStory from './getStory';
import fs from 'fs';
import VideoTemplate from './template-writer/video-template-file';
import TextTemplate from './template-writer/text-template-file';
import getDuration from './getDuration';
import combinedStreams from './combineStream';
import CompositionTemplateFile from './template-writer/composition-template-file';

import GenerateTextFile from './generateTextFile';

const {exec} = require('child_process');
const feature: number = fs.readdirSync('./stories').length;
async function loopStories() {
/** below **/
let listOfVideos = []
// // loop new stories
const fileName = Date.now();


const numberOfPosts = 3;

fs.mkdirSync(`./curated-list/${feature}`)
fs.mkdirSync(`./whole-story-text/${feature}`)
// console.log('number of posts, ', numberOfPosts)
fs.mkdirSync(`./combined/${feature}`)
fs.mkdirSync(`./stories/${feature}`)
fs.mkdirSync(`./random-video-links/${feature}`)

for (let i = 0; i < numberOfPosts; i++) {
//
// // join into one file... so we can generate the text file.
await getStory(feature, i, feature)
}

const latestFile = Date.now();
await combinedStreams(`./stories/${feature}`, latestFile, feature, numberOfPosts)
//
//
// // used combined audio
const featureAudioFile = fs.readdirSync(`./combined/${feature}`);
//
// // should only have one feature audio track per folder.
// copy this to the src folder.
const audioFileDuration = await getDuration(`./combined/${feature}/${featureAudioFile[0]}`);
//
const videoList = await getVideo(randomWords())
//
const organisedList = organiseVideoByRating(videoList);
listOfVideos.push(organisedList);

console.log(audioFileDuration)

// handle if list of video is shorter than audio length...
const curatedList = await enoughVideos(organisedList, audioFileDuration);
//console.log(curatedList)
const curatedListDuration = curatedList.reduce((currentValue, previousValue) => ({duration: currentValue.duration + previousValue.duration}), {duration: 0});
console.log(`should be ${audioFileDuration} but is actually:: `, curatedListDuration);




fs.writeFileSync(`./curated-list/${feature}/1.txt`, '');
curatedList.forEach((videoUrls) => {
if(videoUrls.videos.large.url){
console.log(videoUrls.videos.large.url)
fs.appendFileSync(`./curated-list/${feature}/1.txt`, videoUrls.videos.large.url + ',' + videoUrls.duration + '\n');
}
})




// * fps substitude the 30
exec(`node_modules/.bin/cypress run --env duration=${curatedListDuration.duration * 30},fileUpto=${feature}`)

/** above is all good **/



/** above **/



/** NOTES BELOW **/
// could potentially skip the step where we write it to file.
// - only if I can figure out how to pass the file paths as args into cypress... need to write those to file.


// currently we can get a reddit post, combined audio into one file, get video, of enough duration and get links to that video.

//TOD
// have a script run cypress (after writing the intermediate video file links to file)
// have cypress write the finalized links to file.
// next we need to generate the file using remotion... bring that package into here.
// generate a video template file in remotion... looping through the list of videos.
// look into reading the text file in... and playing as part of the sequence (sync to the audio).



/** NOTES ABOVE **/




}

loopStories();

//
// loopStories();





6 changes: 3 additions & 3 deletions template-writer/text-template-file.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,14 @@ const TextTemplate = (text: string[]) => {
"paddingRight: 10,\n" +
"transform:" + "`" + "scale(" + "$" + "{" + "spring" + "({\n" +
"fps: 30,\n" +
"frame: -1* (" + `${z * 100}` + "- (frame - i * 5)),\n" +
"frame: -1* (" + `${z * 120}` + "- (frame - i * 5)),\n" +
"config: {\n" +
"damping: 100,\n" +
"stiffness: 200,\n" +
"mass: 0.5,\n" +
"}\n" +
"})})" + "`,\n" +
"marginBottom: 25,\n" +
"marginBottom: 85,\n" +
"display: 'inline-block'\n" +
"}}\n" +
'>' +
Expand All @@ -59,7 +59,7 @@ const TextTemplate = (text: string[]) => {
"return " + "(\n" +
"<>\n" +
`${text.map((textLine, i) => {
return "<Sequence from={" + i * 100 +"} durationInFrames={100}>" +
return "<Sequence from={" + i * 120 +"} durationInFrames={120}>" +
"{" + "val"+i + "(" + ")" + "}" + "\n" +
"</Sequence>\n"
}).join('')}\n` +
Expand Down
4 changes: 2 additions & 2 deletions template-writer/video-template-file.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ export interface VideoList {

const VideoTemplate = (videoList: VideoList[], audioFilePath: string) => {
return "import {AbsoluteFill} from 'remotion';\n" +
"import {Video} from 'remotion';\n" +
"import {Video, Audio} from 'remotion';\n" +
"import TransitionSeries from 'remotion-transition-series';\n" +
"import {TextRead} from './text';\n" +
`import audio from '${audioFilePath}'\n` +
Expand All @@ -20,7 +20,7 @@ const VideoTemplate = (videoList: VideoList[], audioFilePath: string) => {
${videoList.map((videoUrl: VideoList) => {
return "<TransitionSeries.Sequence" + " durationInFrames=" + '{' + `${videoUrl.duration}` + '}' + '>' + '\n' +
"<AbsoluteFill>" + '\n' +
"<Video volume=" + "{" + 0 + "}" + "src=" + "'" + `${videoUrl.url}` + "'" + "/>" + '\n' +
"<Video volume=" + "{" + 0 + "} " + "src=" + "'" + `${videoUrl.url}` + "'" + "/>" + '\n' +
"</AbsoluteFill>" + '\n' +
"</TransitionSeries.Sequence>" + '\n' +
"<TransitionSeries.Transition " + '\n' +
Expand Down