Skip to content

Instantly share code, notes, and snippets.

@mrjones-plip
Last active October 26, 2020 19:50
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mrjones-plip/9975f4a180382b54ac9be8ef58ce4903 to your computer and use it in GitHub Desktop.
Save mrjones-plip/9975f4a180382b54ac9be8ef58ce4903 to your computer and use it in GitHub Desktop.

the terrible idea: php youtube-dl downloader with html5 autoplayer

what

a PHP script that wraps around youtube-dl which allows you to enter in a youtube ID. The script then downloads the entire video at the highest resolution and uses javascript to write an HTML5 video element to the page which in turn autoplays the video you just downloaded.

this is a terrible idea and most likely against youtube's TOS - don't use it! Further, after I wrote this I found alltube (github or alltubedownload.net), which is almost identical to this project, but WAY more fancy. Use that instead!

why

for me, it's more like why not!? here's why for me:

  • no trackers
  • no ads
  • no "playing next!"
  • no recommendations
  • no buffering mid video (just possibly a very long wait before it even starts ;)
  • no low quality video
  • no toxic comments
  • all video, all the time

why can't i just paste in a URL?

This is the alpha version! maybe later ;)

install

Assumes you're on ubuntu:

  • create a dir with mkdir that's in a web accessible location on an ubuntu machine
  • install youtube-dl and pafy so they're accsible by apache:
sudo mkdir /var/www/.local
sudo mkdir /var/www/.cache
sudo chown www-data.www-data /var/www/.local
sudo chown www-data.www-data /var/www/.cache
sudo -H -u www-data pip install youtube-dl pafy
  • Install PHP and ffmpeg with sudo apt install php ffmpeg
  • install jquery with something like curl https://code.jquery.com/jquery-3.4.1.min.js -o jquery.min.js
  • install this gist in the web accessible dir curl -o index.php https://gist.githubusercontent.com/Ths2-9Y-LqJt6/9975f4a180382b54ac9be8ef58ce4903/raw/422bb555901b8e341c81372db2dd4f4c216ba178/index.php
  • make sure your web user can write to dir with something like chown www-data .
  • partaaaay!
<?php
if (isset($_GET['url'])) {
$baseUrl = 'https://www.youtube.com/watch?v=';
$ytdl = '/var/www/.local/bin/youtube-dl';
$saveHere = __DIR__ . '/deleteme';
// youtub IDs only have alpha numeric plus '_' & '-', this regex makes it safe for exec
$finalUrl = $baseUrl . preg_replace("/[^a-zA-Z0-9_\-]+/", "", $_GET['url']);
if(!is_executable($ytdl)){
print json_encode(array(
'error' => "$ytdl is not a valid path for youtube-dl :(",
'success' => false
));
} else {
$command = "$ytdl $finalUrl --quiet -o $saveHere -f 'bestvideo[ext=mp4]+bestaudio[ext=m4a]/mp4' --print-json";
exec("rm {$saveHere}.mp4");
exec($command,$result2);
$videoInfo = '';
$title = 'NA';
$description = 'NA';
if (is_array($result2) && isset($result2[0])) {
$resultAry = json_decode($result2[0]);
foreach ($resultAry as $key => $value){
if (is_array($value) || is_object($value) || trim($value) === '') continue;
$videoInfo .= "<b>$key:</b> $value<br/>";
if ($key == 'title'){
$title = $value;
}
if ($key == 'description'){
$description = $value;
}
}
}
print json_encode(array(
'success' => true,
'url' => $finalUrl,
'title' => $title,
'description' => $description,
'command' => "<pre>" . print_r($command,1) ."</pre>",
'result' => '<br />' . $videoInfo ,
));
}
} else { ?>
<script src="./jquery.min.js"></script>
<form method="post" action="./" id="url_form">
Youtube ID: <input type="text" name="url" id="url">
</form>
<script>
function makeid(length) {
var result = '';
var characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
var charactersLength = characters.length;
for ( var i = 0; i < length; i++ ) {
result += characters.charAt(Math.floor(Math.random() * charactersLength));
}
return result;
}
$("#url_form").submit(function(e){
e.preventDefault();
$('#wait').show();
$('#title').hide();
$('#video').hide();
$('#description').hide();
$("#info").html('');
var url = $('#url').val();
$.getJSON( "./?url=" + url, function(result) {
$('#wait').hide();
if (result.success == false) {
$("#info").html(result.error);
} else if(result.success == true) {
$("#info").html('final url: ' + result.url + "<br/><br/>");
$("#info").append('command called: <code>' + result.command + "</code><br/><br/>");
$("#info").append('result, if any: ' + result.result + "<br/><br/>");
$('#title').html(result.title).show();
$('#description').html(result.description).show();
$('#video').attr('src','deleteme.mp4?' + makeid(10)).show();
}
});
});
</script>
<span style="display: none" id="wait" class="spinner"></span>
<h1 id="title"></h1>
<video autoplay controls style="width:100%; display:none;" id="video">
<source src="" type="video/mp4">
</video>
<div id="description"></div>
<div id="info">Pick one!</div>
<style>
@keyframes spinner {
to {transform: rotate(360deg);}
}
.spinner:before {
content: '';
box-sizing: border-box;
position: absolute;
top: 50%;
left: 50%;
width: 80px;
height: 80px;
margin-top: -10px;
margin-left: -10px;
border-radius: 50%;
border: 2px solid transparent;
border-top-color: #07d;
border-bottom-color: #07d;
animation: spinner .8s ease infinite;
}
</style>
<?php }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment