Spaces:
Paused
Paused
File size: 5,402 Bytes
d145b59 f55911c d145b59 16bd39e bf41958 d145b59 bf41958 908b2dc 8062168 d0cc56e bf41958 d0cc56e bf41958 d0cc56e bf41958 d0cc56e 908b2dc bf41958 d145b59 bf41958 d145b59 bf41958 d145b59 bf41958 d145b59 bf41958 b7b3447 d145b59 b7b3447 d145b59 908b2dc d145b59 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 |
/* 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 }; |