forked from sergiotarxz/Peertube-dl
parent
a03a7f947c
commit
7d22cfe5c4
@ -22,10 +22,14 @@ post '/api' => sub {
|
||||
status => 400
|
||||
)
|
||||
);
|
||||
my $format = $c->req->json->{format};
|
||||
my $render_returned;
|
||||
eval {
|
||||
$render_returned = $c->render(
|
||||
json => Peertube::DL::URLHandler::getDownloadDataFromURL($url) );
|
||||
json => Peertube::DL::URLHandler::getDownloadDataFromURL(
|
||||
$url, { ( ( defined $format ) ? ( format => $format ) : () ) },
|
||||
)
|
||||
);
|
||||
};
|
||||
if ($@) {
|
||||
return $c->render( text => $@, status => 500 );
|
||||
|
@ -31,6 +31,14 @@ sub youtube {
|
||||
my $microformat =
|
||||
$ytInitialPlayerResponse->{microformat}{playerMicroformatRenderer};
|
||||
$ytInitialPlayerResponse = $ytInitialPlayerResponse->{streamingData};
|
||||
say Data::Dumper::Dumper [
|
||||
scalar @{ $ytInitialPlayerResponse->{adaptiveFormats} }
|
||||
? @{ $ytInitialPlayerResponse->{adaptiveFormats} }
|
||||
: (),
|
||||
scalar @{ $ytInitialPlayerResponse->{formats} }
|
||||
? @{ $ytInitialPlayerResponse->{formats} }
|
||||
: ()
|
||||
];
|
||||
|
||||
if ( defined $options->{format} ) {
|
||||
my $format = $options->{format};
|
||||
@ -116,26 +124,64 @@ sub youtube {
|
||||
? @{ $ytInitialPlayerResponse->{formats} }
|
||||
: ()
|
||||
];
|
||||
my @formats = map {
|
||||
{
|
||||
id => $_->{itag},
|
||||
mimeType => $_->{mimeType},
|
||||
(
|
||||
( defined $_->{averageBitrate} && defined $_->{bitrate} )
|
||||
? ( bitrate => $_->{averageBitrate} // $_->{bitrate} )
|
||||
: ()
|
||||
),
|
||||
(
|
||||
( defined $_->{qualityLabel} )
|
||||
? ( qualityLabel => int( $_->{qualityLabel} ) )
|
||||
: ()
|
||||
),
|
||||
(
|
||||
( defined $_->{audioSampleRate} )
|
||||
? ( audioSampleRate => $_->{audioSampleRate} )
|
||||
: ()
|
||||
),
|
||||
(
|
||||
( defined $_->{quality} )
|
||||
? ( quality => $_->{quality} )
|
||||
: ()
|
||||
),
|
||||
}
|
||||
} (
|
||||
scalar @{ $ytInitialPlayerResponse->{adaptiveFormats} }
|
||||
? @{ $ytInitialPlayerResponse->{adaptiveFormats} }
|
||||
: (),
|
||||
scalar @{ $ytInitialPlayerResponse->{formats} }
|
||||
? @{ $ytInitialPlayerResponse->{formats} }
|
||||
: ()
|
||||
);
|
||||
my $video_formats = [
|
||||
sort {
|
||||
$b->{qualityLabel} <=> $a->{qualityLabel}
|
||||
|| $b->{bitrate} <=> $a->{bitrate}
|
||||
} grep { defined $_->{qualityLabel} } @formats
|
||||
];
|
||||
my $audio_formats = [
|
||||
sort {
|
||||
$a->{audioSampleRate} <=> $b->{audioSampleRate}
|
||||
|| $b->{bitrate} <=> $a->{bitrate}
|
||||
} grep {
|
||||
defined $_->{audioSampleRate}
|
||||
&& $_->{mimeType} =~ /webm;/
|
||||
} @formats
|
||||
];
|
||||
|
||||
return {
|
||||
options => { list_formats => 1 },
|
||||
title => $microformat->{title}{simpleText},
|
||||
description => $microformat->{description}{simpleText},
|
||||
formats => [
|
||||
map {
|
||||
{
|
||||
id => $_->{itag},
|
||||
mimeType => $_->{mimeType}
|
||||
}
|
||||
} (
|
||||
scalar @{ $ytInitialPlayerResponse->{adaptiveFormats} }
|
||||
? @{ $ytInitialPlayerResponse->{adaptiveFormats} }
|
||||
: (),
|
||||
scalar @{ $ytInitialPlayerResponse->{formats} }
|
||||
? @{ $ytInitialPlayerResponse->{formats} }
|
||||
: ()
|
||||
)
|
||||
]
|
||||
formats => {
|
||||
video_formats => $video_formats,
|
||||
audio_formats => $audio_formats,
|
||||
},
|
||||
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -66,7 +66,7 @@ sub getDownloadDataFromURL {
|
||||
die "No title." unless defined $download_data->{title};
|
||||
die "No description." unless defined $download_data->{description};
|
||||
die "No formats available." unless defined $download_data->{formats};
|
||||
die "Formats is not an arrayref." unless ref $download_data->{formats} eq 'ARRAY';
|
||||
die "Formats is not a hash." unless ref $download_data->{formats} eq 'HASH';
|
||||
say "The video title is $download_data->{title}.";
|
||||
say "The video description is $download_data->{description}.";
|
||||
say "The available formats are: @{[Data::Dumper::Dumper $download_data->{formats}]}.";
|
||||
|
@ -135,7 +135,7 @@ h2 {
|
||||
width: 10%;
|
||||
}
|
||||
|
||||
.poping-notice {
|
||||
#poping-notice {
|
||||
display: none;
|
||||
position: fixed;
|
||||
top: 50%;
|
||||
@ -150,17 +150,17 @@ h2 {
|
||||
overflow-y: scroll;
|
||||
}
|
||||
|
||||
.poping-notice.active {
|
||||
#poping-notice.active {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.poping-notice-container-bar {
|
||||
#poping-notice-container-bar {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
font-size: 5rem;
|
||||
}
|
||||
|
||||
.close-poping-notice {
|
||||
#close-poping-notice {
|
||||
width: 150px;
|
||||
height: 150px;
|
||||
align-items: center;
|
||||
@ -173,7 +173,7 @@ h2 {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.close-poping-notice:hover,.close-poping-notice:focus {
|
||||
#close-poping-notice:hover,#close-poping-notice:focus {
|
||||
background: black;
|
||||
color: white;
|
||||
}
|
||||
@ -229,18 +229,22 @@ h2 {
|
||||
|
||||
.format-list > div {
|
||||
width: 100%;
|
||||
display: grid;
|
||||
grid-auto-columns: 50%;
|
||||
grid-template-areas: "a a";
|
||||
}
|
||||
|
||||
.format-list > div > a {
|
||||
border: 1px solid black;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 5rem;
|
||||
font-size: 1.5rem;
|
||||
padding-right: 5%;
|
||||
padding-left: 5%;
|
||||
text-decoration: none;
|
||||
color: black;
|
||||
background: grey;
|
||||
background: #eee;
|
||||
}
|
||||
|
||||
.format-list > div > a:hover {
|
||||
@ -259,7 +263,7 @@ div.video-formats a {
|
||||
}
|
||||
|
||||
@media (min-width: 668px) {
|
||||
.poping-notice {
|
||||
#poping-notice {
|
||||
width: 629px;
|
||||
}
|
||||
}
|
||||
|
@ -12,6 +12,21 @@
|
||||
<button class="block" id="download-form-button" >Fetch from api</button>
|
||||
</form>
|
||||
</div>
|
||||
<div id="modal-format-selector">
|
||||
<div class="video-container-bar">
|
||||
<a id="close-modal-format-selector">x</a>
|
||||
</div>
|
||||
<h2>Example video</h2>
|
||||
<p>Example description</p>
|
||||
<div class="format-list">
|
||||
<h3>Video Formats.</h3>
|
||||
<div class="video-formats">
|
||||
</div>
|
||||
<h3>Audio Formats.</h3>
|
||||
<div class="audio-formats">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="modal-loading">
|
||||
<embed src="img/spinner.svg"/>
|
||||
</div>
|
||||
@ -30,37 +45,23 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="modal-format-selector" class="active">
|
||||
<div class="video-container-bar">
|
||||
<a id="close-modal-format-selector">x</a>
|
||||
</div>
|
||||
<h2>Example video</h2>
|
||||
<p>Example description</p>
|
||||
<div class="format-list">
|
||||
<div class="video-formats">
|
||||
<a href="18">18</a>
|
||||
</div>
|
||||
<div class="audio-formats">
|
||||
<a href="251">251</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="poping-notice">
|
||||
<p>This webpage is free as in freedom software, it is offered to you with the hope it will be useful, but without any warranty,
|
||||
you can find the source code at <a href="https://gitea.sergiotarxz.freemyip.com/sergiotarxz/Peertube-dl">my gitea</a> with docs to setup your own
|
||||
webpage like this, this software is licensed under the AGPLv3 license which means you MUST convey the source code in a human readable form
|
||||
if you distribute this software or use it as an service to users of service or distributees.<p>
|
||||
<div id="poping-notice-content">
|
||||
<p>This webpage is free as in freedom software, it is offered to you with the hope it will be useful, but without any warranty,
|
||||
you can find the source code at <a href="https://gitea.sergiotarxz.freemyip.com/sergiotarxz/Peertube-dl">my gitea</a> with docs to setup your own
|
||||
webpage like this, this software is licensed under the AGPLv3 license which means you MUST convey the source code in a human readable form
|
||||
if you distribute this software or use it as an service to users of service or distributees.<p>
|
||||
|
||||
<p>I hope that if you find a non supported url which should be supported, a bug, or a feature you would like this webpage to have you file an issue in
|
||||
<a href="https://gitea.sergiotarxz.freemyip.com/sergiotarxz/Peertube-dl/issues">https://gitea.sergiotarxz.freemyip.com/sergiotarxz/Peertube-dl/issues</a>
|
||||
to help this software improve since I find tracking users a pretty bad way to discover bugs and potential good features.</p>
|
||||
<p>I hope that if you find a non supported url which should be supported, a bug, or a feature you would like this webpage to have you file an issue in
|
||||
<a href="https://gitea.sergiotarxz.freemyip.com/sergiotarxz/Peertube-dl/issues">https://gitea.sergiotarxz.freemyip.com/sergiotarxz/Peertube-dl/issues</a>
|
||||
to help this software improve since I find tracking users a pretty bad way to discover bugs and potential good features.</p>
|
||||
|
||||
<p>This webpage may load third party resources depending on the url you give to it which may put cookies in your browser, you are
|
||||
encouraged to frecuently delete your browser cookies to avoid those third parties tracking you on internet, Firefox offers you an
|
||||
option to delete cookies as soon as you close the browser which may be a good idea to enable in the orwellian internet of today.</p>
|
||||
<p>This webpage may load third party resources depending on the url you give to it which may put cookies in your browser, you are
|
||||
encouraged to frecuently delete your browser cookies to avoid those third parties tracking you on internet, Firefox offers you an
|
||||
option to delete cookies as soon as you close the browser which may be a good idea to enable in the orwellian internet of today.</p>
|
||||
</div>
|
||||
<div class="poping-notice-container-bar">
|
||||
<a class="close-poping-notice" href="#">X</a>
|
||||
<div id="poping-notice-container-bar">
|
||||
<a id="close-poping-notice" href="#">X</a>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
@ -15,26 +15,77 @@ let url;
|
||||
let popingNotice;
|
||||
let popingNoticeContent;
|
||||
let closePopingNotice;
|
||||
let titleModalFormatSelector;
|
||||
let descriptionModalFormatSelector;
|
||||
let modalFormatSelector;
|
||||
let videoFormats;
|
||||
let audioFormats;
|
||||
let closeModalFormatSelector;
|
||||
|
||||
function downloadFormButtonHandler(event) {
|
||||
event.preventDefault();
|
||||
modalLoading.classList.add('active');
|
||||
getRealURL(downloadFormUrl.value).then( (response) => {
|
||||
video.src = response.url;
|
||||
filename = response.filename;
|
||||
url = response.url;
|
||||
video.addEventListener('canplay', (event) => {
|
||||
modalLoading.classList.remove('active');
|
||||
modalVideoContainer.style.display = 'block';
|
||||
});
|
||||
askForURL(downloadFormUrl.value);
|
||||
}
|
||||
function askForURL(url, format) {
|
||||
getRealURL(url, format).then( (response) => {
|
||||
if ( response.options !== undefined && response.options.list_formats !== undefined && response.options.list_formats ) {
|
||||
titleModalFormatSelector.innerText = response.title;
|
||||
descriptionModalFormatSelector.innerText = response.description;
|
||||
videoFormats.innerHTML = '';
|
||||
audioFormats.innerHTML = '';
|
||||
for ( let x of response.formats.audio_formats) {
|
||||
let a = document.createElement('a');
|
||||
a.innerText = 'Id: ' + x.id + "\n"
|
||||
+ 'Format: ' + x.mimeType + "\n"
|
||||
+ 'AudioSampleRate: ' + x.audioSampleRate + "\n"
|
||||
+ 'Bitrate: ' + x.bitrate + ".\n";
|
||||
a.addEventListener( 'click', (event) => {
|
||||
modalLoading.classList.add('active');
|
||||
askForURL(url, x.id );
|
||||
});
|
||||
audioFormats.appendChild(a);
|
||||
modalLoading.classList.remove('active');
|
||||
modalFormatSelector.classList.add('active');
|
||||
}
|
||||
for ( let x of response.formats.video_formats ) {
|
||||
let a = document.createElement('a');
|
||||
a.innerText = 'Id: ' + x.id + "\n"
|
||||
+ 'Format: ' + x.mimeType + "\n"
|
||||
+ 'QualityLabel: ' + x.qualityLabel + "p\n"
|
||||
+ 'Bitrate: ' + x.bitrate + "\n"
|
||||
+ (
|
||||
( x.audioSampleRate !== undefined ) ?
|
||||
'AudioSampleRate: ' + x.audioSampleRate + ".\n" :
|
||||
"No audio."
|
||||
);
|
||||
a.addEventListener( 'click', (event) => {
|
||||
modalLoading.classList.add('active');
|
||||
askForURL(url, x.id );
|
||||
});
|
||||
videoFormats.appendChild(a);
|
||||
modalLoading.classList.remove('active');
|
||||
modalFormatSelector.classList.add('active');
|
||||
}
|
||||
} else {
|
||||
video.src = response.url;
|
||||
filename = response.filename;
|
||||
url = response.url;
|
||||
video.addEventListener('canplay', (event) => {
|
||||
modalLoading.classList.remove('active');
|
||||
modalVideoContainer.style.display = 'block';
|
||||
});
|
||||
}
|
||||
return true;
|
||||
}).catch ( (error) => {
|
||||
console.log(error);
|
||||
modalLoading.classList.remove('active');
|
||||
popingNoticeContent.innerHTML = '';
|
||||
let p = document.createElement('p');
|
||||
p.appendChild(document.createTextNode('The url '));
|
||||
let input_url = document.createElement('a');
|
||||
input_url.href = downloadFormUrl.value;
|
||||
input_url.innerText = downloadFormUrl.value;
|
||||
input_url.href = url;
|
||||
input_url.innerText = url;
|
||||
p.appendChild(input_url)
|
||||
p.appendChild(document.createTextNode(' is not supported, if you think this is an error, report it '));
|
||||
let issues_url = 'https://gitea.sergiotarxz.freemyip.com/sergiotarxz/Peertube-dl/issues';
|
||||
@ -45,6 +96,7 @@ function downloadFormButtonHandler(event) {
|
||||
p.appendChild(document.createTextNode('.'));
|
||||
popingNoticeContent.appendChild(p);
|
||||
popingNotice.classList.add('active');
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
@ -86,7 +138,10 @@ async function generateBlobVideoByProxy(url) {
|
||||
return blob;
|
||||
}
|
||||
|
||||
async function getRealURL(url) {
|
||||
async function getRealURL(url, format) {
|
||||
let request = { url: url };
|
||||
if (format !== undefined)
|
||||
request.format = format;
|
||||
const response = await fetch('/api', {
|
||||
method: 'POST',
|
||||
mode: 'cors',
|
||||
@ -94,7 +149,7 @@ async function getRealURL(url) {
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({url: url}),
|
||||
body: JSON.stringify(request),
|
||||
});
|
||||
return response.json();
|
||||
}
|
||||
@ -118,14 +173,23 @@ window.addEventListener('load', (event) => {
|
||||
downloadVideoPrepare = document.querySelector('#download-video-prepare');
|
||||
closeAndResetVideoContainer = document.querySelector('#close-and-reset-video-container');
|
||||
modalLoading = document.querySelector('#modal-loading');
|
||||
popingNotice = document.querySelector('.poping-notice');
|
||||
popingNoticeContent = document.querySelector('.poping-notice-content');
|
||||
closePopingNotice = document.querySelector('.close-poping-notice');
|
||||
popingNotice = document.querySelector('#poping-notice');
|
||||
popingNoticeContent = document.querySelector('#poping-notice-content');
|
||||
closePopingNotice = document.querySelector('#close-poping-notice');
|
||||
titleModalFormatSelector = document.querySelector('#modal-format-selector h2');
|
||||
descriptionModalFormatSelector = document.querySelector('#modal-format-selector p');
|
||||
modalFormatSelector = document.querySelector('#modal-format-selector');
|
||||
videoFormats = document.querySelector('#modal-format-selector .video-formats');
|
||||
audioFormats = document.querySelector('#modal-format-selector .audio-formats');
|
||||
closeModalFormatSelector = document.querySelector('#close-modal-format-selector');
|
||||
|
||||
downloadFormButton.addEventListener('click', downloadFormButtonHandler);
|
||||
downloadVideoPrepare.addEventListener('click', downloadVideoPrepareHandler);
|
||||
downloadForm.addEventListener('submit', downloadFormHandler);
|
||||
closeAndResetVideoContainer.addEventListener('click', closeAndResetVideoContainerHandler);
|
||||
closeModalFormatSelector.addEventListener('click', (event) => {
|
||||
modalFormatSelector.classList.remove('active');
|
||||
});
|
||||
closePopingNotice.addEventListener('click', (event) => {
|
||||
popingNotice.classList.remove('active');
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user