Black detect ffmpeg and use in a javascript - javascript

I had an ffmpeg script that allow me to detect black frames from a video file sample from the bottom.
and i want to create a javascript code that will allow me to do the same function sample from the bottom but its not working.
original code from ffmpeg script:
`ffmpeg -i LKE-BLACK.mp4 -vf "blackdetect=d=0.5:pix_th=0.10" -an -f null - 2>&1 | findstr blackdetect > output.txt
node script:
var fs = require('fs');
const ffmpeg = require("ffmpeg.js");
var createStream = fs.createWriteStream("data.txt");
createStream.end();
const transcode = async ({ target: { files } }) => {
message.innerHTML = 'Loading ffmpeg-core.js';
await ffmpeg.load();
message.innerHTML = 'Start transcoding';
await ffmpeg.transcode('-i', 'LKE-BLACK.mp4', "-vf", "blackdetect=d=0.5:pix_th=0.10", '-an', '-f', 'null - 2>&1', );
message.innerHTML = 'Complete transcoding';
fs.writeFile("data.txt", function (err) {
if (err) throw err;
console.log('File is created successfully.');
});
}

Related

deferReply() cannot solve DiscordAPIError[10062]: Unknown interaction

I am trying to make a discord bot with discordJS (v14) and I followed the tutorial from
https://discordjs.guide/creating-your-bot/slash-commands.html#individual-command-files and created a slash command. However, when I call the slash command, it always shoe DiscordAPIError[10062]: Unknown interaction I tried to use the command await interaction.deferReply() but it still failed.
Here are my code of that function
play.js
const { SlashCommandBuilder } = require("discord.js");
module.exports = {
data: new SlashCommandBuilder()
.setName("play")
.setDescription("Play the song from the url or search query")
.addStringOption(option =>
option.setName("query")
.setDescription("The url or search query")
.setRequired(true)
),
async execute(interaction) {
console.log("interaction received"); // This part can run
await interaction.deferReply()
console.log("play command executed"); // cannot run
await interaction.editReply({ content: interaction.options.getString("query"), ephemeral: true });
}
}
index.js
const fs = require('node:fs');
const path = require('node:path');
const {
Client,
Collection,
Events,
GatewayIntentBits,
REST,
Routes,
} = require('discord.js');
require("dotenv").config();
// Tokens
const BOT_TOKEN = process.env.DISCORD_TOKEN;
const CLIENT_ID = process.env.CLIENT_ID;
// Create a new client instance
const client = new Client({ intents: [GatewayIntentBits.Guilds] });
const rest = new REST({ version: 10 }).setToken(BOT_TOKEN);
// When the client is ready, run this code (only once)
// We use 'c' for the event parameter to keep it separate from the already defined 'client'
client.once(Events.ClientReady, c => {
console.log(`Ready! Logged in as ${c.user.tag}`);
});
// Create a new collection for commands
client.commands = new Collection();
const commandsPath = path.join(__dirname, 'commands');
const commandFiles = fs.readdirSync(commandsPath).filter(file => file.endsWith('.js'));
for (const file of commandFiles) {
const filePath = path.join(commandsPath, file);
const command = require(filePath);
// Set a new item in the Collection with the key as the command name and the value as the exported module
if ('data' in command && 'execute' in command) {
client.commands.set(command.data.name, command);
} else {
console.log(`[WARNING] The command at ${filePath} is missing a required "data" or "execute" property.`);
}
}
client.on(Events.InteractionCreate, async interaction => {
if (!interaction.isChatInputCommand()) return;
console.log(interaction);
const command = interaction.client.commands.get(interaction.commandName);
if (!command) {
console.error(`No command matching ${interaction.commandName} was found.`);
return;
}
console.log(`Executing ${interaction.commandName} command.`);
try {
await command.execute(interaction);
} catch (error) {
console.error(error);
await interaction.reply({ content: 'There was an error while executing this command!', ephemeral: true });
}
});
const commands = [];
// Grab the SlashCommandBuilder#toJSON() output of each command's data for deployment
for (const file of commandFiles) {
const command = require(`./commands/${file}`);
console.log(command.data.toJSON());
commands.push(command.data.toJSON());
}
// try to register the slash commands
(async () => {
try {
console.log(`Started refreshing ${commands.length} application (/) commands.`);
// The put method is used to fully refresh all commands in the guild with the current set
const data = await rest.put(
Routes.applicationCommands(CLIENT_ID),
{ body: commands },
);
console.log(`Successfully reloaded ${data.length} application (/) commands.`);
// Log in to Discord with your client's token
client.login(BOT_TOKEN);
} catch (error) {
// And of course, make sure you catch and log any errors!
console.error(error);
}
})();
The terminal result shows that it received the message but it continue to have the error
DiscordAPIError[10062]: Unknown interaction
May I ask how can I solve the problem and why it would happen?

Function is running twice but only being called once?

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());

Electron and NodeJS: Execute shell command asyncronously with live stream

Electron: get file conversion percent in real-time:
I wanna run the command ffmpeg -i video.mp4 (example) to convert a video into another format. But I want to get the conversion percent that is streamed in the process output and get it in my Electron App or NodeJS.
I've tried all methods: spawn fork exec and all of them return me the last line of the process output. I want a LIVE Stream of each line that is been written, to show the percent progress.
I've tried:
Fork
const {fork} = require('child_process')
const forked = fork('ffmpeg -i video.mp4');
forked.on('message', (msg) => {
console.log(msg);
})
Exec Alternative 1
const execFile = require('child_process').execFile;
execFile('ffmpeg -i video.mp4', [], (e, stdout, stderr) => {
if (e instanceof Error){
console.error(e);
}
console.log('stdout ', stdout)
console.log('stderr ', stderr);
})
Exec Alternative 2
const exec = require('child_process').exec;
exec('ffmpeg -i video.mp4', (error, stdout, stderr) => {
console.log(stdout);
});
/*EXEC Alternative 2*/
const exec = require('child_process').exec;
const proccessing = exec('ffmpeg -i video.mp4');
proccessing.stdout.on('data', function(data) {
console.log(data);
});
proccessing.stdout.pipe(process.stdout);
Spawn
const spawn = require('child_process').spawn,
const processing = spawn('ffmpeg -i video.mp4');
processing .stdout.on('data', function (data) {
console.log('stdout: ' + data.toString());
});
processing .stderr.on('data', function (data) {
console.log('stderr: ' + data.toString());
});
processing .on('exit', function (code) {
console.log('code ' + code.toString());
});
SUMMARY:
🎯Goal:
Get this results in the console
10% converted
15% converted
20% converted
100% converted...
❌Error:
What I'm getting:
100% converted
//Sometimes I get an empty string because it is the last line of the .exe script
BEFORE MARK AS DUPLICATE, I'M SURE NO ONE ANSWER IN STACKOVERFLOW WORKED FOR ME
You need to use ffmpeg with ffmpeg-progress-wrapper. Attach on event "progress" and get the "progress" property.
process.on('progress', (progress) => console.log(JSON.stringify(progress.progress));
It goes from 0 to 1, so you will need to set some adjusts.

How to solve timeout problem with electron-html-to node.js

I'm experiencing this timeout when trying to use electron to convert an html file to pdf. I'm running this js app through node.
`{ Error: Worker Timeout, the worker process does not respond after 10000 ms
at Timeout._onTimeout (C:\Users\Owner\Desktop\code\PDF-Profile-Generator\node_modules\electron-workers\lib\ElectronManager.js:377:21)
at ontimeout (timers.js:436:11)
at tryOnTimeout (timers.js:300:5)
at listOnTimeout (timers.js:263:5)
at Timer.processTimers (timers.js:223:10)
workerTimeout: true,
message:
Worker Timeout, the worker process does not respond after 10000 ms,
electronTimeout: true }`
I do not know too much about electron. I have not been able to try too much to try to debug it. The js code is meant to generate an html file based on user input, pulling from a github profile. Then, that html file needs to be converted to a pdf file.
My js code is as follows:
const fs = require("fs")
const convertapi = require('convertapi')('tTi0uXTS08ennqBS');
const path = require("path");
const generate = require("./generateHTML");
const inquirer = require("inquirer");
const axios = require("axios");
const questions = ["What is your Github user name?", "Pick your favorite color?"];
function writeToFile(fileName, data) {
return fs.writeFileSync(path.join(process.cwd(), fileName), data);
};
function promptUser() {
return inquirer.prompt([
{
type: "input",
name: "username",
message: questions[0]
},
{
type: "list",
name: "colorchoice",
choices: ["green", "blue", "pink", "red"],
message: questions[1]
}
])
};
function init() {
promptUser()
.then(function ({ username, colorchoice }) {
const color = colorchoice;
const queryUrl = `https://api.github.com/users/${username}`;
let html;
axios
.get(queryUrl)
.then(function (res) {
res.data.color = color
const starArray = res.data.starred_url.split(",")
res.data.stars = starArray.length
console.log(res)
html = generate(res.data);
console.log(html)
writeToFile("profile.html", html)
})
var convertFactory = require('electron-html-to');
var conversion = convertFactory({
converterPath: convertFactory.converters.PDF
});
conversion({ file: './profile.html' }, function (err, result) {
if (err) {
return console.error(err);
}
console.log(result.numberOfPages);
console.log(result.logs);
result.stream.pipe(fs.createWriteStream(__dirname + '/profile.pdf'));
conversion.kill(); // necessary if you use the electron-server strategy, see bellow for details
});
// convertapi.convert('pdf', { File: './profile.html' })
// .then(function (result) {
// // get converted file url
// console.log("Converted file url: " + result.file.url);
// // save to file
// return result.file.save(__dirname + "/profile.pdf");
// })
// .then(function (file) {
// console.log("File saved: " + file);
// });
})
}
init();
I had a similar problem. I had installed multiple versions of Electron (electron, electron-html-to, electron-prebuilt), and the problem was resolved when I deleted the older versions in package.json so only one was left. The assumption is that they were interfering with each other.
So check the installed versions of electron, because the problem might be there rather than your code.

Data stream handlers and CLI incorporation Node JS

I am trying to create an interactive CLI that can run serial commands. I have two files serialcomms.js and cli.js. Serialcomms.js contains the connection, handlers, and command functions. cli.js contains the commander information.
My issue is that I can only call the send command once because the listeners/handlers take over from the serialcomms file. What would be the best method to loop the cli program so I can call the send command over and over again, but still have the serial handlers running and output to stdout? Would I need to use a child process? Or recursion to have the cli call itself?
Example behavior I am expecting with an echo bot on the other end of the serial line.
Send hello
hello
Send Bye
Bye
Behavior I am experiencing
Send hello
hello
endless wait
Here is my serialcomms.js
const SerialPort = require('serialport');
const ReadLine = require('#serialport/parser-readline');
let portName = `/dev/pts/${process.argv[2]}` || '/dev/pts/6';
let baudRate = process.argv[3] || 115200;
let myPort = new SerialPort(portName, {baudRate: baudRate})
let parser = myPort.pipe(new ReadLine({ delimiter: '\n' }))
myPort.on('open', () => {
console.log(`port ${portName} open`)
})
parser.on('data', (data) => {
console.log(data)
})
myPort.on('close', () => {
console.log(`port ${portName} closed`)
})
myPort.on('error', (err) => {
console.error('port error: ' + err)
})
function send(data){
myPort.write(JSON.stringify(data)+'\n', function(err) {
if (err) {
return console.log('Error on write: ', err.message);
}
console.log(`${data} sent`);
});
}
module.exports = {
send
}
Here is my CLI.js file
const program = require('commander');
const {send} = require('./serialcomms');
program
.version('1.0.0')
.description('Serial Tester')
program
.command('send <msg>')
.alias('s')
.description('send a message over serial')
.action((msg)=>{
send(msg)
})
program.parse(process.argv)

Categories

Resources