/* 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 };