Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
"phpstan/phpstan": "^2.0"
},
"config": {
"sort-packages": true
"sort-packages": true,
"process-timeout": 600
}
}
35 changes: 35 additions & 0 deletions public/convert.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
if(isset($_GET["youtubelink"]) && !empty($_GET["youtubelink"]))
{
$youtubelink = $_GET["youtubelink"];
$startAt = $_GET["startAt"] ?? null;
$endAt = $_GET["endAt"] ?? null;
$format = $_GET['format'] ?? 'mp3';

if(!in_array($format, POSSIBLE_FORMATS))
Expand All @@ -31,6 +33,36 @@

$exists = file_exists(env('DOWNLOAD_FOLDER').$id.".".$format);

if (!empty($startAt) || !empty($endAt))
{
if (!empty($startAt) && !empty($endAt))
{
if ((int)$startAt >= (int)$endAt)
{
http_response_code(400);
die(json_encode(array("error" => true, "message" => "Invalid time range: startAt must be less than endAt")));
}
}

$query = parse_url($youtubelink, PHP_URL_QUERY);
parse_str($query, $params);

if (!empty($startAt))
$params['start'] = $startAt;

if (!empty($endAt))
$params['end'] = $endAt;

$youtubelink = strtok($youtubelink, '?') . '?' . http_build_query($params);

if ($exists)
{
//todo this can probably go when youtube-dl-php supports --force-overwrites options
unlink(env('DOWNLOAD_FOLDER').$id.".".$format);
$exists = false;
}
}

if(env('DOWNLOAD_MAX_LENGTH', 0) > 0 || $exists)
{
try {
Expand Down Expand Up @@ -69,6 +101,9 @@
->cookies(file_exists(env('COOKIE_FILE')) ? env('COOKIE_FILE') : null)
->url($youtubelink);

if (!empty($startAt) || !empty($endAt))
$options = $options->downloadSections('*from-url');

if($format == 'mp3')
{
$options = $options->extractAudio(true)
Expand Down
32 changes: 30 additions & 2 deletions public/index.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
<div class="row">
<div class="col-lg-8">
<div class="form-floating mb-3">
<input type="text" name="youtubelink" class="form-control" id="link" required placeholder="youtube.com" />
<input type="text" name="youtubelink" class="form-control" id="link" onchange="fillStartEnd()" onkeyup="fillStartEnd()" required placeholder=" " />
<label for="link">Youtube url</label>
</div>
</div>
Expand All @@ -39,7 +39,35 @@
</div>
</div>

<button type="submit" class="btn btn-outline-primary"><i class="fas fa-sync-alt"></i> Convert</button>
<div class="row">
<div class="col-lg-12">
<div class="input-group">
<span class="input-group-text">
<i class="fa-solid fa-forward-step"></i>
</span>

<div class="form-floating">
<input type="number" class="form-control" min="0" name="startAt" id="startAt" placeholder=" " />
<label for="startAt">Start</label>
</div>

<div class="form-floating">
<input type="number" class="form-control" min="0" name="endAt" id="endAt" placeholder=" " />
<label for="endAt">End</label>
</div>

<span class="input-group-text">
<i class="fa-solid fa-backward-step"></i>
</span>
</div>
<div class="form-text">
Specify start and/or end times <b>(in seconds)</b> to trim the video. Leave both empty to download the complete video.<br/>
Start time only: downloads from that point to the end. End time only: downloads from the beginning to that point.
</div>
</div>
</div>

<button type="submit" class="btn btn-outline-primary mt-4"><i class="fas fa-sync-alt"></i> Convert</button>
</form>
</div>
</div>
Expand Down
43 changes: 42 additions & 1 deletion public/script.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,19 @@ document.addEventListener('DOMContentLoaded', () => {
const submitButton = frmConvert.querySelector("button[type=submit]");
const link = document.getElementById('link').value;
const format = document.getElementById('format').value;
const startAt = document.getElementById('startAt').value;
const endAt = document.getElementById('endAt').value;

submitButton.classList.add("disabled");
submitButton.innerHTML = "<i class=\"fas fa-spin fa-sync-alt\"></i> Converting...";

const endpoint = `${frmConvert.getAttribute("action")}?youtubelink=${link}&format=${format}`;
let endpoint = `${frmConvert.getAttribute("action")}?youtubelink=${link}&format=${format}`;

if (startAt.length > 0)
endpoint += `&startAt=${startAt}`;

if (endAt.length > 0)
endpoint += `&endAt=${endAt}`;

fetch(endpoint)
.then(response => response.json())
Expand Down Expand Up @@ -168,4 +176,37 @@ function handleInfoResponse(data, submitButton)
tableCells[9].innerText = data.title;
tableCells[10].innerHTML = `<a target='_blank' href='${data.url}'>${data.url}</a>`;
}
}

function fillStartEnd()
{
const elLink = document.getElementById('link');
const elStart = document.getElementById('startAt');
const elEnd = document.getElementById('endAt');

const url = new URL(elLink.value);
const start = url.searchParams.get("start") || url.searchParams.get("t");
const end = url.searchParams.get("end");

if (start && start.length > 0)
{
elStart.value = start;
elStart.setAttribute('readonly', 'readonly');
}
else
{
elStart.value = '';
elStart.removeAttribute('readonly');
}

if (end && end.length > 0)
{
elEnd.value = end;
elEnd.setAttribute('readonly', 'readonly');
}
else
{
elEnd.value = '';
elEnd.removeAttribute('readonly');
}
}