This code works. It throws an error on the first getClipFile, because ffmpeg hasn't completed. I kind of understand that, but also it's running again somehow?
I want to make it run once, after the my bash script has completed. I also cannot understand how to simply wrap it all in a function and just wait on it.
Thanks! The JS:
const gameModel = require('../models/gameSchema')
const fs = require("fs");
const { MessageAttachment } = require('discord.js')
const { exec } = require('child_process')
module.exports = {
name: 'contestsubmit',
async execute(message, args, client, Discord ) {
const channel = await client.channels.cache.get('830145067738071092')
const bashScript = "/home/ubuntu/smashbot/utils/clipper.sh"
const youtubeURL = args[0]
const clipStart = +(args[1].split(':').reduce((acc,time) => (60 * acc) + +time))
const clipEnd = +(args[2].split(':').reduce((acc,time) => (60 * acc) + +time))
const clipID = message.id
const clipType = "Play"
let i = "";
message.delete()
const myShellScript = exec(`sh ${bashScript} "${youtubeURL}" ${clipType} ${clipStart} ${clipEnd} ${clipID}`)
myShellScript.stdout.on('data', (data) => {
i += '23'
console.log('i==================',i)
getClipFile()
})
myShellScript.stderr.on('data', (data) => {
console.error(data);
})
const getClipFile = () => {
fs.readFile(`/home/ubuntu/smashbot/clip-${clipType}-${clipID}.mp4`, (err, data) => {
if (err) {
console.error(err)
return
}
const stats = fs.statSync(`/home/ubuntu/smashbot/clip-${clipType}-${clipID}.mp4`);
const fileSizeInBytes = stats.size
console.log('FILE SIZE', fileSizeInBytes)
const videoAttachment = new MessageAttachment(data, `${clipID}.mp4`)
channel.send(`**Nominated for Play of the Week!**`, videoAttachment)
console.log('sending clip?')
})}
}}
The bash:
#!/bin/bash
if [ $# -ne 5 ]; then
echo 'Illegal number of parameters. Needs parameters:'
echo 'Usage:'
echo './clipper.sh YOUTUBE_URL FILE GAME_START GAME_END'
echo
echo 'Parameters:'
echo ' - YOUTUBE_URL No "https://", just the youtube.com'
echo ' - CLIP_TYPE: Clip Type: Choose "Play" or "Life"'
echo ' - CLIP_START: Start time of game in seconds'
echo ' - CLIP_END: Emd time of game in seconds'
echo ' (video format and quality options etc.)'
exit 1
fi
YOUTUBE_URL="$1"
CLIP_TYPE="$2"
CLIP_START="$3"
CLIP_END="$4"
INDEX="$5"
# Filename of the source video (without extension)
BASENAME="${CLIP_TYPE%.*}"
# Extension for the video parts
EXTENSION="mp4"
# Filename of the next video part
NEXTFILENAME="clip-$BASENAME-$INDEX.$EXTENSION"
# Encode next part
echo ffmpeg -ss $CLIP_START -i youtube-dl -f 22 --get-url $YOUTUBE_URL -to $CLIP_END -c copy $NEXTFILENAME
ffmpeg -i $(youtube-dl -f 22 --get-url $YOUTUBE_URL) -ss $CLIP_START -to $CLIP_END -c copy $NEXTFILENAME
echo "Clipped $CLIP_TYPE: starts at $CLIP_START and ends at $CLIP_END"
You need to wait for the end
event before calling getClipFile()
. You're calling it every time you get a buffer of data.
myShellScript.stdout.on('data', (data) => {
i += '23'
console.log('i==================',i)
});
myShellScript.stdout.on('end', () => getClipFile());