Implement showing video you just selected

This commit is contained in:
Reimar 2025-01-28 19:31:11 +01:00
parent 964f49e9ef
commit 39fa99da63
Signed by: Reimar
GPG Key ID: 93549FA07F0AE268
4 changed files with 121 additions and 35 deletions

View File

@ -2,6 +2,7 @@ async function compress() {
showSection("loading");
const filesize = document.getElementById("filesize").value;
const filesizeUnit = document.getElementById("filesize-unit").value;
const file = document.getElementById("file-input").files[0];
const ffmpeg = new FFmpegWASM.FFmpeg();
@ -13,30 +14,27 @@ async function compress() {
await ffmpeg.writeFile(file.name, await readFromBlob(file));
await ffmpeg.exec(["-i", file.name, "-fs", filesize + "M", "compressed.mp4"]);
await ffmpeg.exec(["-i", file.name, "-preset", "ultrafast", "-fs", filesize + filesizeUnit, "compressed.mp4"]);
const video = await ffmpeg.readFile("compressed.mp4");
location.href = URL.createObjectURL(new Blob([video.buffer], { type: "video/mp4" }));
}
function selectFile() {
function openFileSelector() {
document.getElementById("file-input").click();
}
function showSection(section) {
for (const section of document.getElementsByTagName("section")) {
section.style.opacity = "0";
}
function selectFile() {
setTimeout(() => {
for (const section of document.getElementsByTagName("section")) {
section.style.display = "none";
}
const file = document.getElementById("file-input").files[0];
document.getElementById(section + "-section").style.display = "block";
document.getElementById(section + "-section").style.opacity = "1";
}, 400);
document.getElementById("uploaded-video").src = URL.createObjectURL(file);
document.getElementById("uploaded-video").load();
hideElements("#file-drop-area", "#file-input-spacing");
showElements("#uploaded-video", "#change-file");
}, 200);
}
// https://github.com/ffmpegwasm/ffmpeg.wasm/blob/main/packages/util/src/index.ts

View File

@ -0,0 +1,43 @@
const TRANSITION_TIME = 300;
function showSection(section) {
for (const section of document.getElementsByTagName("section")) {
hideElements(section);
}
showElements(`#${section}-section`);
}
function hideElements() {
for (const input of arguments) {
const elem = input instanceof Element ? input : document.querySelector(input);
if (getComputedStyle(elem).display === "none")
continue;
elem.style.opacity = "0";
elem.dataset.oldDisplay = getComputedStyle(elem).display;
setTimeout(() => {
elem.style.display = "none";
}, TRANSITION_TIME);
}
}
function showElements() {
setTimeout(() => {
for (const input of arguments) {
const elem = input instanceof Element ? input : document.querySelector(input);
elem.style.opacity = "0";
elem.style.display = elem.dataset.oldDisplay || "block";
elem.dataset.oldDisplay = null;
setTimeout(() => {
elem.style.opacity = "1";
}, 10);
}
}, TRANSITION_TIME);
}

View File

@ -20,36 +20,44 @@ h1 {
margin-bottom: 1rem;
}
h3 {
color: #757575;
font-size: 4rem;
font-weight: 400;
margin: 0;
}
p {
color: #9E9E9E;
font-size: 0.8rem;
}
section {
transition: opacity ease-in 400ms;
* {
opacity: 1;
transition: opacity 300ms;
}
#file-input {
video {
width: 355px;
height: 200px;
border: 2px solid #212121;
background-color: black;
border-radius: 1rem;
box-shadow: 0 5px 5px rgba(0, 0, 0, 0.2);
}
#file-input, #change-file {
display: none;
opacity: 0;
}
#file-input-spacing * {
visibility: hidden;
}
#file-drop-area {
max-width: 355px;
height: 200px;
height: 198px;
border: 3px dotted #BDBDBD;
margin: 3rem auto;
margin: 3rem auto 1rem auto;
border-radius: 1rem;
display: flex;
justify-content: center;
align-items: center;
transition: background-color ease-in 200ms;
transition: all 300ms;
cursor: pointer;
}
@ -62,7 +70,13 @@ section {
outline: none;
}
button {
#uploaded-video {
display: none;
opacity: 0;
margin: 3rem auto 1rem auto;
}
button.primary {
background-image: linear-gradient(to right, #4CAF50, #00BCD4);
border: none;
color: white;
@ -74,19 +88,32 @@ button {
cursor: pointer;
}
button:hover {
button.primary:hover {
filter: brightness(1.1);
}
button:active {
button.primary:active {
filter: brightness(0.8);
}
button:focus {
button.primary:focus {
box-shadow: 0 4px 4px rgba(0, 0, 0, 0.2);
outline: 2px solid black;
}
button.simple {
border: none;
background-color: transparent;
transition: color 100ms;
cursor: pointer;
color: #9E9E9E;
margin: 1rem auto;
}
button.simple:hover {
color: black;
}
input, select {
background-color: white;
padding: 0.5rem 1rem;
@ -121,3 +148,14 @@ input:focus, select:focus {
margin-left: 1rem;
}
#loading-title {
color: #757575;
font-size: 3rem;
font-weight: bold;
margin-top: 2rem;
}
#loading-description {
font-size: 1rem;
}

View File

@ -4,6 +4,7 @@
<meta charset="UTF-8">
<title>Video Compressor</title>
<script defer src="/assets/scripts/ffmpeg/package/dist/umd/ffmpeg.js"></script>
<script defer src="/assets/scripts/ui.js"></script>
<script defer src="/assets/scripts/main.js"></script>
<link rel="stylesheet" href="/assets/style/main.css">
</head>
@ -12,10 +13,16 @@
<p>Compress video files to a specific file size, so you can upload them to your favorite social media and messaging apps!</p>
<section id="file-picker-section">
<div id="file-drop-area" onclick="selectFile()" onkeydown="['Enter', 'Space'].includes(event.code) && selectFile()" tabindex="0">
<div id="file-drop-area" onclick="openFileSelector()" onkeydown="['Enter', 'Space'].includes(event.code) && openFileSelector()" tabindex="0">
<span>Drag and drop a file here!</span>
</div>
<input id="file-input" type="file" accept="video/*" tabindex="-1">
<input id="file-input" oninput="selectFile()" type="file" accept="video/*" tabindex="-1">
<div id="file-input-spacing" style="margin-top: -1rem">
<button class="simple">.</button>
</div>
<video id="uploaded-video" controls autoplay></video>
<button id="change-file" onclick="openFileSelector()" class="simple">Change video</button>
<input id="filesize" type="number" value="10" size="3" placeholder="#"><!--
@ -25,12 +32,12 @@
<option value="G">GB</option>
</select>
<button id="compress" onclick="compress()">Go!</button>
<button id="compress" onclick="compress()" class="primary">Go!</button>
</section>
<section id="loading-section" style="opacity: 0; display: none;">
<h3>Please wait...</h3>
<p>This may take a while</p>
<h3 id="loading-title">Please wait...</h3>
<p id="loading-description">This may take a while</p>
</section>
</body>
</html>