hutatools / lib /skrep.js
fullpwerr's picture
Update lib/skrep.js
908b2dc verified
/* eslint-disable jsdoc/require-jsdoc */
const axios = require("axios");
const FormData = require("form-data");
const fs = require("fs");
const { exec } = require("child_process");
const path = require("path");
async function ttt(link) {
try {
const form = new FormData();
form.append("url", link);
form.append("count", "12");
form.append("cursor", "0");
form.append("web", "1");
form.append("hd", "1");
const { data } = await axios.post("https://www.tikwm.com/api/", form);
if (data.code === 0 && data.msg === "success") {
const baseUrl = "https://www.tikwm.com";
data.data.cover = baseUrl + data.data.cover;
data.data.play = baseUrl + data.data.play;
data.data.wmplay = baseUrl + data.data.wmplay;
data.data.hdplay = baseUrl + data.data.hdplay;
data.data.music = baseUrl + data.data.music;
data.data.author.avatar = baseUrl + data.data.author.avatar;
}
const res = {
status: 200,
type: "tiktok",
title: data.data?.title || null,
desc: null,
thumbnail: data.data.cover,
video: [{ url: data.data.hdplay }, { url: data.data.play }],
music: [{ url: data.data.music }],
image: data.data.images,
};
/*
if (res.image) {
const outputDir = path.join(__dirname, "../tmp")
await downloadImages(res.image, outputDir);
const FNvd = `tt_video_${Date.now()}.mp4`;
const FNad = `tt_audio_${Date.now()}.mp3`;
const videoPath = `${outputDir}/${FNvd}`;
const audioPath = `${outputDir}/${FNad}`;
// βœ… Unduh audio sebelum dipakai
await downloadAudio(res.music[0].url, audioPath);
const slideResult = await createSlideshow(outputDir, videoPath, audioPath);
if (slideResult) {
res.video.push({ resolusi: "Slideshow", url: `https://fullperr-hutatools.hf.space/tmp/${FNvd}`});
}
}*/
return res;
} catch (e) {
return { status: 500, message: e.message };
}
}
async function downloadAudio(audioUrl, outputFile) {
const response = await axios({
url: audioUrl,
responseType: "stream",
});
return new Promise((resolve, reject) => {
const writer = fs.createWriteStream(outputFile);
response.data.pipe(writer);
writer.on("finish", () => {
console.log(`βœ… Audio telah diunduh: ${outputFile}`);
resolve(outputFile);
});
writer.on("error", reject);
});
}
async function downloadImages(imageUrls, outputDir) {
if (!fs.existsSync(outputDir)) fs.mkdirSync(outputDir);
let downloadPromises = imageUrls.map((url, index) => {
const filePath = `${outputDir}/image${index + 1}.jpg`;
return axios({ url, responseType: "stream" }).then((response) => {
return new Promise((resolve, reject) => {
const writer = fs.createWriteStream(filePath);
response.data.pipe(writer);
writer.on("finish", resolve);
writer.on("error", reject);
});
});
});
await Promise.all(downloadPromises);
console.log("βœ… Semua gambar telah diunduh.");
}
async function getAudioDuration(audioFile) {
return new Promise((resolve, reject) => {
exec(
`ffprobe -i ${audioFile} -show_entries format=duration -v quiet -of csv="p=0"`,
(error, stdout) => {
if (error) {
reject("❌ Gagal mendapatkan durasi audio.");
return;
}
resolve(parseFloat(stdout.trim()));
}
);
});
}
async function createSlideshow(imagesDir, outputVideo, audioFile) {
const imageFiles = fs
.readdirSync(imagesDir)
.filter((file) => file.endsWith(".jpg"));
const totalImages = imageFiles.length;
if (totalImages === 0) {
console.error("❌ Tidak ada gambar untuk slideshow.");
return null;
}
try {
let audioDuration = await getAudioDuration(audioFile);
if (audioDuration > 25) {
console.log("⏳ Audio lebih dari 25 detik, membatasi ke 25 detik.");
audioDuration = 25;
}
const outputDir = path.join(__dirname, "../tmp")
const frameDuration = audioDuration / totalImages;
const tempDirv = `${outputDir}/temp_video_${Date.now()}.mp4`;
console.log(`πŸ“ Durasi audio: ${audioDuration}s`);
console.log(`πŸ–Ό Durasi per gambar: ${frameDuration}s`);
const ffmpegCommand = `ffmpeg -framerate 1/${frameDuration} -i ${imagesDir}/image%d.jpg -filter_complex "pad=iw:ih:(ow-iw)/2:(oh-ih)/2" -r 25 -c:v libx264 -pix_fmt yuv420p ${tempDirv}`;
console.log("πŸš€ Membuat slideshow...");
return new Promise((resolve, reject) => {
exec(ffmpegCommand, (error) => {
if (error) {
console.error("❌ Error saat membuat slideshow:", error);
reject(null);
return;
}
console.log("βœ… Slideshow selesai dibuat.");
const audioCommand = `ffmpeg -i ${tempDirv} -i ${audioFile} -filter_complex "[1:a]apad" -shortest -c:v libx264 -pix_fmt yuv420p -c:a aac -b:a 128k ${outputVideo}`;
exec(audioCommand, (audioError) => {
if (audioError) {
console.error("❌ Error saat menambahkan audio:", audioError);
reject(null);
return;
}
console.log("βœ… Video dengan audio selesai dibuat.");
console.log("🧹 Folder gambar sementara dihapus.");
resolve(outputVideo);
});
});
});
} catch (error) {
console.error(error);
return null;
}
}
module.exports = { ttt };