From 394535560a54de7c8c8328b77773f0bf715b43ef Mon Sep 17 00:00:00 2001 From: FujiwaraChoki Date: Sun, 11 Feb 2024 11:18:25 +0100 Subject: [PATCH] Update environment variables and video generation script --- .env.example | 2 +- Backend/video.py | 4 +- EnvironmentVariables.md | 13 +++-- Frontend/app.js | 116 +++++++++++++++++++++++++++++++++++++++ Frontend/index.html | 119 +--------------------------------------- 5 files changed, 129 insertions(+), 125 deletions(-) create mode 100644 Frontend/app.js diff --git a/.env.example b/.env.example index 96b2c6de..20120884 100644 --- a/.env.example +++ b/.env.example @@ -3,4 +3,4 @@ ASSEMBLY_AI_API_KEY="" # Optional TIKTOK_SESSION_ID="" IMAGEMAGICK_BINARY="" # Download from https://imagemagick.org/script/download.php PEXELS_API_KEY="" # Get from https://www.pexels.com/api/ -OPENAI_API_KEY="" # Get from https://platform.openai.com/docs/quickstart?context=python \ No newline at end of file +OPENAI_API_KEY="" # Optional \ No newline at end of file diff --git a/Backend/video.py b/Backend/video.py index 3be70a0a..65a2ec11 100644 --- a/Backend/video.py +++ b/Backend/video.py @@ -158,10 +158,10 @@ def combine_videos(video_paths: List[str], max_duration: int, max_clip_duration: for video_path in video_paths: clip = VideoFileClip(video_path) clip = clip.without_audio() - # check if clip is longer than the remaning audio + # Check if clip is longer than the remaining audio if (max_duration - tot_dur) < clip.duration: clip = clip.subclip(0, (max_duration - tot_dur)) - # only shorten clips if the calculated clip length (req_dur) is shorter than the actual clip to prevent still image + # Only shorten clips if the calculated clip length (req_dur) is shorter than the actual clip to prevent still image elif req_dur < clip.duration: clip = clip.subclip(0, req_dur) clip = clip.set_fps(30) diff --git a/EnvironmentVariables.md b/EnvironmentVariables.md index 5fee2ba2..16f28cd2 100644 --- a/EnvironmentVariables.md +++ b/EnvironmentVariables.md @@ -1,12 +1,17 @@ # Environment Variables ## Required -- ASSEMBLY_AI_API_KEY: Your unique AssemblyAI API key is required. You can obtain one [here](https://www.assemblyai.com/app/) This field is optional; if left empty, the subtitle will be created based on the generated script. - TIKTOK_SESSION_ID: Your TikTok session ID is required. Obtain it by logging into TikTok in your browser and copying the value of the `sessionid` cookie. -- IMAGEMAGICK_BINARY: The filepath to the ImageMagick binary (.exe file) is needed. Obtain it [here](https://imagemagick.org/script/download.php) +- IMAGEMAGICK_BINARY: The filepath to the ImageMagick binary (.exe file) is needed. Obtain it [here](https://imagemagick.org/script/download.php). -- PEXELS_API_KEY: Your unique Pexels API key is required. Obtain yours [here](https://www.pexels.com/api/) +- PEXELS_API_KEY: Your unique Pexels API key is required. Obtain yours [here](https://www.pexels.com/api/). -Open an issue if you need help with any of these. +## Optional + +- OPENAI_API_KEY: Your unique OpenAI API key is required. Obtain yours [here](https://platform.openai.com/api-keys), only nessecary if you want to use the OpenAI models. + +* ASSEMBLY_AI_API_KEY: Your unique AssemblyAI API key is required. You can obtain one [here](https://www.assemblyai.com/app/). This field is optional; if left empty, the subtitle will be created based on the generated script. Subtitles can also be created locally. + +Join the [Discord](https://dsc.gg/fuji-community) for support and updates. diff --git a/Frontend/app.js b/Frontend/app.js new file mode 100644 index 00000000..7c878700 --- /dev/null +++ b/Frontend/app.js @@ -0,0 +1,116 @@ +const videoSubject = document.querySelector("#videoSubject"); +const aiModel = document.querySelector("#aiModel"); +const voice = document.querySelector("#voice"); +const zipUrl = document.querySelector("#zipUrl"); +const paragraphNumber = document.querySelector("#paragraphNumber"); +const youtubeToggle = document.querySelector("#youtubeUploadToggle"); +const useMusicToggle = document.querySelector("#useMusicToggle"); +const generateButton = document.querySelector("#generateButton"); +const cancelButton = document.querySelector("#cancelButton"); + +const cancelGeneration = () => { + console.log("Canceling generation..."); + // Send request to /cancel + fetch("http://localhost:8080/api/cancel", { + method: "POST", + headers: { + "Content-Type": "application/json", + Accept: "application/json", + }, + }) + .then((response) => response.json()) + .then((data) => { + alert(data.message); + console.log(data); + }) + .catch((error) => { + alert("An error occurred. Please try again later."); + console.log(error); + }); + + // Hide cancel button + cancelButton.classList.add("hidden"); + + // Enable generate button + generateButton.disabled = false; + generateButton.classList.remove("hidden"); +}; + +const generateVideo = () => { + console.log("Generating video..."); + // Disable button and change text + generateButton.disabled = true; + generateButton.classList.add("hidden"); + + // Show cancel button + cancelButton.classList.remove("hidden"); + + // Get values from input fields + const videoSubjectValue = videoSubject.value; + const aiModelValue = aiModel.value; + const voiceValue = voice.value; + const paragraphNumberValue = paragraphNumber.value; + const youtubeUpload = youtubeToggle.checked; + const useMusicToggleState = useMusicToggle.checked; + const zipUrlValue = zipUrl.value; + + const url = "http://localhost:8080/api/generate"; + + // Construct data to be sent to the server + const data = { + videoSubject: videoSubjectValue, + aiModel: aiModelValue, + voice: voiceValue, + paragraphNumber: paragraphNumberValue, + automateYoutubeUpload: youtubeUpload, + useMusic: useMusicToggleState, + zipUrl: zipUrlValue, + }; + + // Send the actual request to the server + fetch(url, { + method: "POST", + body: JSON.stringify(data), + headers: { + "Content-Type": "application/json", + Accept: "application/json", + }, + }) + .then((response) => response.json()) + .then((data) => { + console.log(data); + alert(data.message); + // Hide cancel button after generation is complete + generateButton.disabled = false; + generateButton.classList.remove("hidden"); + cancelButton.classList.add("hidden"); + }) + .catch((error) => { + alert("An error occurred. Please try again later."); + console.log(error); + }); +}; + +generateButton.addEventListener("click", generateVideo); +cancelButton.addEventListener("click", cancelGeneration); + +videoSubject.addEventListener("keyup", (event) => { + if (event.key === "Enter") { + generateVideo(); + } +}); + +// Load the data from localStorage on page load +document.addEventListener("DOMContentLoaded", (event) => { + const voiceSelect = document.getElementById("voice"); + const storedVoiceValue = localStorage.getItem("voiceValue"); + + if (storedVoiceValue) { + voiceSelect.value = storedVoiceValue; + } +}); + +// When the voice select field changes, store the new value in localStorage. +document.getElementById("voice").addEventListener("change", (event) => { + localStorage.setItem("voiceValue", event.target.value); +}); diff --git a/Frontend/index.html b/Frontend/index.html index 1aa26616..09a5ae72 100644 --- a/Frontend/index.html +++ b/Frontend/index.html @@ -162,123 +162,6 @@

MoneyPrinter

- +