-
-
Save LuigiElleBalotta/d5f30cbed74e808d67ad44d3f9506d31 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** PHP Class yt_downloader | |
* ================================================================================ | |
* PHP class to retreive the file location of Youtube videos, download the video | |
* files to a local path and/or convert the videos into mp3 audio files. | |
* ================================================================================ | |
* @category | |
* @package yt_downloader | |
* @version CVS: $Id: youtube-dl.class.php,v1.0.2 2012/12/10 01:49:01 ssc Exp $ | |
* @author Stephan Schmitz <eyecatchup@gmail.com> | |
* @copyright 2012 - present, Stephan Schmitz | |
* @license http://eyecatchup.mit-license.org | |
* @link https://github.com/eyecatchup/php-yt_downloader/ | |
* ================================================================================ | |
* LICENSE: Permission is hereby granted, free of charge, to any person obtaining | |
* a copy of this software and associated documentation files (the "Software"), | |
* to deal in the Software without restriction, including without limitation the | |
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
* copies of the Software, and to permit persons to whom the Software is furnished | |
* to do so, subject to the following conditions: | |
* | |
* The above copyright notice and this permission notice shall be included in all | |
* copies or substantial portions of the Software. | |
* | |
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY | |
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | |
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |
* ================================================================================ | |
*/ | |
// Ensure the PHP extensions CURL and JSON are installed. | |
if (!function_exists('curl_init')) { | |
throw new Exception('Script requires the PHP CURL extension.'); | |
exit(0); | |
} | |
if (!function_exists('json_decode')) { | |
throw new Exception('Script requires the PHP JSON extension.'); | |
exit(0); | |
} | |
// Downloading HD Videos may take some time. | |
ini_set('max_execution_time', 0); | |
// Writing HD Videos to your disk, may need some extra resources. | |
ini_set('memory_limit', '1024M'); | |
// Include the config interface. | |
require('youtube-dl.config.php'); | |
// Include helper functions for usort. | |
require('comparisonfunctions.usort.php'); | |
/** | |
* yt_downloader Class | |
*/ | |
class yt_downloader implements cnfg | |
{ | |
/** | |
* Class constructor method. | |
* @access public | |
* @return void | |
*/ | |
public function __construct($str=NULL, $instant=FALSE, $out=NULL) | |
{ | |
// Required YouTube URLs. | |
$this->YT_BASE_URL = "https://www.youtube.com/"; | |
$this->YT_INFO_URL = $this->YT_BASE_URL . "get_video_info?video_id=%s&el=embedded&ps=default&eurl=&hl=en_US"; | |
$this->YT_INFO_ALT = $this->YT_BASE_URL . "oembed?url=%s&format=json"; | |
$this->YT_THUMB_URL = "http://img.youtube.com/vi/%s/%s.jpg"; | |
$this->YT_THUMB_ALT = "http://i1.ytimg.com/vi/%s/%s.jpg"; | |
$this->CURL_UA = "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:11.0) Gecko Firefox/11.0"; | |
// Set default parameters for the download instance. | |
$this->audio = FALSE; # Formatted output filename(.ext) of the object's audio output. | |
$this->video = FALSE; # Formatted output filename(.ext) of the object's video output. | |
$this->thumb = FALSE; # Formatted output filename(.ext) of the object's preview image. | |
$this->videoID = FALSE; # YouTube video id. | |
$this->videoExt = FALSE; # Filetype of the object's video ouput file. | |
$this->videoTitle = FALSE; # Formatted output filename by original YouTube video title /wo ext. | |
$this->videoThumb = FALSE; # YouTube URL of the object's preview image. | |
$this->videoQuality = FALSE; # Whether downloading videos at the best quality available. | |
$this->audioQuality = FALSE; # Default audio output sample rate (in kbits). | |
$this->audioFormat = FALSE; # Default audio output filetype. | |
$this->videoThumbSize = FALSE; # Whether default thumbnail size is 120*90, or 480*360 px. | |
$this->defaultDownload = FALSE; # Whether downloading video, or audio is default. | |
$this->downloadThumbs = TRUE; # Whether to download thumnails for downloads (Boolean TRUE/FALSE). | |
$this->downloadsDir = FALSE; # Relative path to the directory to save downloads to. | |
$this->downloadsArray = FALSE; # Array, containing the YouTube URLs of all videos available. | |
$this->FfmpegLogsDir = FALSE; # Absolute path to the directory to save ffmpeg logs to. | |
$this->ffmpegLogfile = FALSE; # Absolute path to the directory to save ffmpeg logs to. | |
$this->FfmpegLogsActive = TRUE; # Whether to log ffmpeg processes (Boolean TRUE/FALSE). | |
self::set_downloads_dir(cnfg::Download_Folder); | |
self::set_ffmpegLogs_dir(cnfg::Ffmpeg_LogsDir); | |
self::set_ffmpegLogs_active(cnfg::Ffmpeg_LogsActive); | |
self::set_default_download(cnfg::Default_Download); | |
self::set_download_thumbnail(cnfg::Download_Thumbnail); | |
self::set_thumb_size(cnfg::Default_Thumbsize); | |
self::set_video_quality(cnfg::Default_Videoquality); | |
self::set_audio_quality(cnfg::Default_Audioquality); | |
self::set_audio_format(cnfg::Default_Audioformat); | |
// Optional constructor argument #1 will be used as YouTube Video-ID. | |
if($str != NULL) { | |
self::set_youtube($str); | |
// Optional constructor argument #2 will start an instant download. | |
if($instant === TRUE) { | |
// Optional constructor argument #3 defines the media type to be saved. | |
self::do_download($out); | |
} | |
} | |
} | |
public function do_download($out) | |
{ | |
$action = ($out == "audio" || $out == "video") ? $out : self::get_default_download(); | |
return ($action == "audio" ) ? self::download_audio() : self::download_video(); | |
} | |
/** | |
* Set the YouTube Video that shall be downloaded. | |
* @access public | |
* @return void | |
*/ | |
public function set_youtube($str) | |
{ | |
/** | |
* Parse input string to determine if it's a Youtube URL, | |
* or an ID. If it's a URL, extract the ID from it. | |
*/ | |
$tmp_id = self::parse_yturl($str); | |
$vid_id = ($tmp_id !== FALSE) ? $tmp_id : $str; | |
/** | |
* Check the public video info feed to check if we got a | |
* valid Youtube ID. If not, throw an exception and exit. | |
*/ | |
$url = sprintf($this->YT_BASE_URL . "watch?v=%s", $vid_id); | |
$url = sprintf($this->YT_INFO_ALT, urlencode($url)); | |
if(self::curl_httpstatus($url) !== 200) { | |
throw new Exception("Invalid Youtube video ID: $vid_id"); | |
exit(); } | |
else { self::set_video_id($vid_id); } | |
} | |
/** | |
* Get the direct links to the YouTube Video. | |
* @access public | |
* @return integer Returns (int)0 if download succeded, or (int)1 if | |
* the video already exists on the download directory. | |
*/ | |
public function get_downloads() | |
{ | |
/** | |
* If we have a valid Youtube Video Id, try to get the real location | |
* and download the video. If not, throw an exception and exit. | |
*/ | |
$id = self::get_video_id(); | |
if($id === FALSE) { | |
throw new Exception("Missing video id. Use set_youtube() and try again."); | |
exit(); | |
} | |
else { | |
/** | |
* Try to parse the YouTube Video-Info file to get the video URL map, | |
* that holds the locations on the YouTube media servers. | |
*/ | |
$v_info = self::get_yt_info(); | |
if(self::get_videodata($v_info) === TRUE) | |
{ | |
$vids = self::get_url_map($v_info); | |
/** | |
* If extracting the URL map failed, throw an exception | |
* and exit. Try to include the original YouTube error | |
* - eg "forbidden by country"-message. | |
*/ | |
if(!is_array($vids) || sizeof($vids) == 0) { | |
$err_msg = ""; | |
if(strpos($v_info, "status=fail") !== FALSE) { | |
preg_match_all('#reason=(.*?)$#si', $v_info, $err_matches); | |
if(isset($err_matches[1][0])) { | |
$err_msg = urldecode($err_matches[1][0]); | |
$err_msg = str_replace("Watch on YouTube", "", strip_tags($err_msg)); | |
$err_msg = "Youtube error message: ". $err_msg; | |
} | |
} | |
return $err_msg; | |
} | |
else { | |
$quality = self::get_video_quality(); | |
if($quality == 1) { | |
usort($vids, 'asc_by_quality'); | |
} else if($quality == 0) { | |
usort($vids, 'desc_by_quality'); | |
} | |
self::set_yt_url_map($vids); | |
return $vids; | |
} | |
} | |
} | |
} | |
/** | |
* Try to download the defined YouTube Video. | |
* @access public | |
* @return integer Returns (int)0 if download succeded, or (int)1 if | |
* the video already exists on the download directory. | |
*/ | |
public function download_video($c=NULL) | |
{ | |
$c = ($c !== NULL) ? $c : 0; | |
/** | |
* If we have a valid Youtube Video Id, try to get the real location | |
* and download the video. If not, throw an exception and exit. | |
*/ | |
$id = self::get_video_id(); | |
if($id === FALSE) { | |
throw new Exception("Missing video id. Use set_youtube() and try again."); | |
exit(); | |
} | |
else { | |
$yt_url_map = self::get_yt_url_map(); | |
if($yt_url_map === FALSE) { | |
$vids = self::get_downloads(); | |
self::set_yt_url_map($vids); | |
} else { | |
$vids = $yt_url_map; | |
} | |
if(!is_array($vids)) { | |
throw new Exception("Grabbing original file location(s) failed. $vids"); | |
exit(); | |
} | |
else { | |
/** | |
* Format video title and set download and file preferences. | |
*/ | |
$title = self::get_video_title(); | |
$path = self::get_downloads_dir(); | |
$YT_Video_URL = $vids[$c]["url"]; | |
$res = $vids[$c]["type"]; | |
$ext = $vids[$c]["ext"]; | |
$videoTitle = $title . "_-_" . $res ."_-_youtubeid-$id"; | |
$videoFilename = "$videoTitle.$ext"; | |
$thumbFilename = "$videoTitle.jpg"; | |
$video = $path . $videoFilename; | |
self::set_video($videoFilename); | |
self::set_thumb($thumbFilename); | |
/** | |
* PHP doesn't cache information about non-existent files. | |
* So, if you call file_exists() on a file that doesn't exist, | |
* it will return FALSE until you create the file. The problem is, | |
* that once you've created a file, file_exists() will return TRUE - | |
* even if you've deleted the file meanwhile and the cache haven't | |
* been cleared! Even though unlink() clears the cache automatically, | |
* since we don't know which way a file may have been deleted (if it existed), | |
* we clear the file status cache to ensure a valid file_exists result. | |
*/ | |
clearstatcache(); | |
/** | |
* If the video does not already exist in the download directory, | |
* try to download the video and the video preview image. | |
*/ | |
if(!file_exists($video)) | |
{ | |
$download_thumbs = self::get_download_thumbnail(); | |
if($download_thumbs === TRUE) { | |
self::check_thumbs($id); | |
} | |
touch($video); | |
chmod($video, 0775); | |
// Download the video. | |
$download = self::curl_get_file($YT_Video_URL, $video); | |
if($download === FALSE) { | |
throw new Exception("Saving $videoFilename to $path failed."); | |
exit(); | |
} | |
else { | |
if($download_thumbs === TRUE) { | |
// Download the video preview image. | |
$thumb = self::get_video_thumb(); | |
if($thumb !== FALSE) | |
{ | |
$thumbnail = $path . $thumbFilename; | |
self::curl_get_file($thumb, $thumbnail); | |
chmod($thumbnail, 0775); | |
} | |
} | |
return 0; | |
} | |
} | |
else { | |
return 1; | |
} | |
} | |
} | |
} | |
public function download_audio() | |
{ | |
$ffmpeg = self::has_ffmpeg(); | |
if($ffmpeg === FALSE) { | |
throw new Exception("You must have Ffmpeg installed in order to use this function."); | |
exit(); | |
} | |
else if($ffmpeg === TRUE) { | |
self::set_video_quality(1); | |
$dl = self::download_video(); | |
if($dl == 0 || $dl == 1) | |
{ | |
$title = self::get_video_title(); | |
$path = self::get_downloads_dir(); | |
$ext = self::get_audio_format(); | |
$ffmpeg_infile = $path . self::get_video(); | |
$ffmpeg_outfile = $path . $title .".". $ext; | |
if(!file_exists($ffmpeg_outfile)) | |
{ | |
// Whether to log the ffmpeg process. | |
$logging = self::get_ffmpegLogs_active(); | |
// Ffmpeg command to convert the input video file into an audio file. | |
$ab = self::get_audio_quality() . "k"; | |
$cmd = "ffmpeg -i \"$ffmpeg_infile\" -ar 44100 -ab $ab -ac 2 \"$ffmpeg_outfile\""; | |
if($logging !== FALSE) | |
{ | |
// Create a unique log file name per process. | |
$ffmpeg_logspath = self::get_ffmpegLogs_dir(); | |
$ffmpeg_logfile = "ffmpeg." . date("Ymdhis") . ".log"; | |
$logfile = "./" . $ffmpeg_logspath . $ffmpeg_logfile; | |
self::set_ffmpeg_Logfile($logfile); | |
// Create new log file (via command line). | |
exec("touch $logfile"); | |
exec("chmod 777 $logfile"); | |
} | |
// Execute Ffmpeg command line command. | |
$Ffmpeg = exec($cmd); | |
$log_it = "echo \"$Ffmpeg\" > \"$logfile\""; | |
$lg = `$log_it`; | |
// If the video did not already existed, delete it (since we probably wanted the soundtrack only). | |
if($dl == 0) { | |
// unlink($ffmpeg_infile); | |
} | |
clearstatcache(); | |
if(file_exists($ffmpeg_outfile) !== FALSE) { | |
self::set_audio($title .".". $ext); | |
return 0; | |
} else { | |
throw new Exception("Something went wrong while converting the video into $ext format, sorry!"); | |
exit(); | |
} | |
} | |
else { | |
self::set_audio($title .".". $ext); | |
return 1; | |
} | |
} | |
} else { | |
throw new Exception("Cannot locate your Ffmpeg installation?! Thus, cannot convert the video into $ext format."); | |
exit(); | |
} | |
} | |
/** | |
* Get filestats for the downloaded audio/video file. | |
* @access public | |
* @return mixed Returns an array containing formatted filestats, | |
* or (boolean) FALSE if file doesn't exist. | |
*/ | |
public function video_stats() | |
{ | |
$file = self::get_video(); | |
$path = self::get_downloads_dir(); | |
clearstatcache(); | |
$filestats = stat($path . $file); | |
if($filestats !== FALSE) { | |
return array( | |
"size" => self::human_bytes($filestats["size"]), | |
"created" => date ("d.m.Y H:i:s.", $filestats["ctime"]), | |
"modified" => date ("d.m.Y H:i:s.", $filestats["mtime"]) | |
); | |
} | |
else { return FALSE; } | |
} | |
/** | |
* Check if input string is a valid YouTube URL | |
* and try to extract the YouTube Video ID from it. | |
* @access private | |
* @return mixed Returns YouTube Video ID, or (boolean) FALSE. | |
*/ | |
private function parse_yturl($url) | |
{ | |
$pattern = '#^(?:https?://)?'; # Optional URL scheme. Either http or https. | |
$pattern .= '(?:www\.)?'; # Optional www subdomain. | |
$pattern .= '(?:'; # Group host alternatives: | |
$pattern .= 'youtu\.be/'; # Either youtu.be, | |
$pattern .= '|youtube\.com'; # or youtube.com | |
$pattern .= '(?:'; # Group path alternatives: | |
$pattern .= '/embed/'; # Either /embed/, | |
$pattern .= '|/v/'; # or /v/, | |
$pattern .= '|/watch\?v='; # or /watch?v=, | |
$pattern .= '|/watch\?.+&v='; # or /watch?other_param&v= | |
$pattern .= ')'; # End path alternatives. | |
$pattern .= ')'; # End host alternatives. | |
$pattern .= '([\w-]{11})'; # 11 characters (Length of Youtube video ids). | |
$pattern .= '(?:.+)?$#x'; # Optional other ending URL parameters. | |
preg_match($pattern, $url, $matches); | |
return (isset($matches[1])) ? $matches[1] : FALSE; | |
} | |
/** | |
* Get internal YouTube info for a Video. | |
* @access private | |
* @return string Returns video info as string. | |
*/ | |
private function get_yt_info() | |
{ | |
$url = sprintf($this->YT_INFO_URL, self::get_video_id()); | |
return self::curl_get($url); | |
} | |
/** | |
* Get the public YouTube Info-Feed for a Video. | |
* @access private | |
* @return mixed Returns array, containing the YouTube Video-Title | |
* and preview image URL, or (boolean) FALSE | |
* if parsing the feed failed. | |
*/ | |
private function get_public_info() | |
{ | |
$url = sprintf($this->YT_BASE_URL . "watch?v=%s", self::get_video_id()); | |
$url = sprintf($this->YT_INFO_ALT, urlencode($url)); | |
$info = json_decode(self::curl_get($url), TRUE); | |
if(is_array($info) && sizeof($info) > 0) { | |
return array( | |
"title" => $info["title"], | |
"thumb" => $info["thumbnail_url"] | |
); | |
} | |
else { return FALSE; } | |
} | |
/** | |
* Get formatted video data from the public YouTube Info-Feed. | |
* @access private | |
* @param string $str Info-File contents for a YouTube Video. | |
* @return mixed Returns the formatted YouTube Video-Title as string, | |
* or (boolean) FALSE if extracting failed. | |
*/ | |
private function get_videodata($str) | |
{ | |
$yt_info = $str; | |
$pb_info = self::get_public_info(); | |
if($pb_info !== FALSE) { | |
$prepared_title = htmlentities(mb_convert_encoding($pb_info["title"], "utf-8")); | |
$htmlTitle = htmlentities(utf8_decode($pb_info["title"]), ENT_QUOTES | ENT_IGNORE, "UTF-8"); | |
$videoTitle = self::canonicalize($htmlTitle); | |
} | |
else { | |
$videoTitle = self::formattedVideoTitle($yt_info); | |
} | |
if(is_string($videoTitle) && strlen($videoTitle) > 0) { | |
self::set_video_title($videoTitle); | |
return TRUE; | |
} | |
else { return FALSE; } | |
} | |
/** | |
* Get the URL map for a YouTube Video. | |
* @access private | |
* @param string $data Info-File contents for a YouTube Video. | |
* @return mixed Returns an array, containg the Video URL map, | |
* or (boolean) FALSE if extracting failed. | |
*/ | |
private function get_url_map($data) | |
{ | |
parse_str($data, $parsed_data); | |
if(empty($parsed_data['player_response'])) { | |
return FALSE; | |
} | |
else { | |
// $json = json_decode($parsed_data); | |
$response = $parsed_data["player_response"]; | |
$responseObj = json_decode($response); | |
$streamingData = $responseObj->streamingData; | |
$tmp = array(); | |
foreach($streamingData->adaptiveFormats as $adaptiveFormat) { | |
$tmp[$adaptiveFormat->itag] = urldecode($adaptiveFormat->url); | |
} | |
// $urls = explode('&',$parsed_data['url_encoded_fmt_stream_map']); | |
// $tmp = array(); | |
// var_dump($urls); | |
// foreach($urls as $url) { | |
// $lines = explode('&',$url); | |
// $num = ''; | |
// $url = ''; | |
// foreach($lines as $u){ | |
// $num = ((empty($num)) && (preg_match("/itag=/i",$u))) ? str_replace("itag=","",$u):$num; | |
// $url = ((empty($url)) && (preg_match("/url=/i",$u))) ? str_replace("url=","",$u):$url; | |
// if((!empty($url)) && ((!empty($num)))){ | |
// $tmp[$num] = urldecode($url); | |
// break; | |
// } | |
// } | |
// } | |
$formats = array( | |
'13' => array('3gp', '240p', '10'), | |
'17' => array('3gp', '240p', '9'), | |
'36' => array('3gp', '320p', '8'), | |
'5' => array('flv', '240p', '7'), | |
'6' => array('flv', '240p', '6'), | |
'34' => array('flv', '320p', '5'), | |
'35' => array('flv', '480p', '4'), | |
'18' => array('mp4', '480p', '3'), | |
'22' => array('mp4', '720p', '2'), | |
'137' => array('mp4', '1080p', '1') | |
); | |
$videos = array(); | |
foreach ($formats as $format => $meta) { | |
if (isset($tmp[$format])) { | |
$videos[] = array('pref' => $meta[2], 'ext' => $meta[0], 'type' => $meta[1], 'url' => $tmp[$format]); | |
} | |
} | |
return $videos; | |
} | |
} | |
/** | |
* Get the preview image for a YouTube Video. | |
* @access private | |
* @param string $id Valid YouTube Video-ID. | |
* @return mixed Returns the image URL as string, | |
* or (boolean) FALSE if no image found. | |
*/ | |
private function check_thumbs($id) | |
{ | |
$thumbsize = self::get_thumb_size(); | |
$thumb_uri = sprintf($this->YT_THUMB_URL, $id, $thumbsize); | |
if(self::curl_httpstatus($thumb_uri) == 200) { | |
$th = $thumb_uri; | |
} | |
else { | |
$thumb_uri = sprintf($this->YT_THUMB_ALT, $id, $thumbsize); | |
if(self::curl_httpstatus($thumb_uri) == 200) { | |
$th = $thumb_uri; | |
} | |
else { $th = FALSE; } | |
} | |
self::set_video_thumb($th); | |
} | |
/** | |
* Get the YouTube Video Title and format it. | |
* @access private | |
* @param string $str Input string. | |
* @return string Returns cleaned input string. | |
*/ | |
private function formattedVideoTitle($str) | |
{ | |
preg_match_all('#title=(.*?)$#si', urldecode($str), $matches); | |
$title = explode("&", $matches[1][0]); | |
$title = $title[0]; | |
$title = htmlentities(utf8_decode($title), ENT_QUOTES | ENT_IGNORE, "UTF-8"); | |
return self::canonicalize($title); | |
} | |
/** | |
* Format the YouTube Video Title into a valid filename. | |
* @access private | |
* @param string $str Input string. | |
* @return string Returns cleaned input string. | |
*/ | |
private function canonicalize($str) | |
{ | |
$str = trim($str); # Strip unnecessary characters from the beginning and the end of string. | |
$str = str_replace(""", "", $str); # Strip quotes. | |
$str = self::strynonym($str); # Replace special character vowels by their equivalent ASCII letter. | |
$str = preg_replace("/[[:blank:]]+/", "_", $str); # Replace all blanks by an underscore. | |
$str = preg_replace('/[^\x9\xA\xD\x20-\x7F]/', '', $str); # Strip everything what is not valid ASCII. | |
$str = preg_replace('/[^\w\d_-]/si', '', $str); # Strip everything what is not a word, a number, "_", or "-". | |
$str = str_replace('__', '_', $str); # Fix duplicated underscores. | |
$str = str_replace('--', '-', $str); # Fix duplicated minus signs. | |
if(substr($str, -1) == "_" OR substr($str, -1) == "-") { | |
$str = substr($str, 0, -1); # Remove last character, if it's an underscore, or minus sign. | |
} | |
return trim($str); | |
} | |
/** | |
* Replace common special entity codes for special character | |
* vowels by their equivalent ASCII letter. | |
* @access private | |
* @param string $str Input string. | |
* @return string Returns cleaned input string. | |
*/ | |
private function strynonym($str) | |
{ | |
$SpecialVowels = array( | |
'À'=>'A', 'à'=>'a', 'È'=>'E', 'è'=>'e', 'Ì'=>'I', 'ì'=>'i', 'Ò'=>'O', 'ò'=>'o', 'Ù'=>'U', 'ù'=>'u', | |
'Á'=>'A', 'á'=>'a', 'É'=>'E', 'é'=>'e', 'Í'=>'I', 'í'=>'i', 'Ó'=>'O', 'ó'=>'o', 'Ú'=>'U', 'ú'=>'u', 'Ý'=>'Y', 'ý'=>'y', | |
'Â'=>'A', 'â'=>'a', 'Ê'=>'E', 'ê'=>'e', 'Î'=>'I', 'î'=>'i', 'Ô'=>'O', 'ô'=>'o', 'Û'=>'U', 'û'=>'u', | |
'Ã'=>'A', 'ã'=>'a', 'Ñ'=>'N', 'ñ'=>'n', 'Õ'=>'O', 'õ'=>'o', | |
'Ä'=>'Ae', 'ä'=>'ae', 'Ë'=>'E', 'ë'=>'e', 'Ï'=>'I', 'ï'=>'i', 'Ö'=>'Oe', 'ö'=>'oe', 'Ü'=>'Ue', 'ü'=>'ue', 'Ÿ'=>'Y', 'ÿ'=>'y', | |
'Å'=>'A', 'å'=>'a', 'Æ'=>'Ae', 'æ'=>'ae', 'Ç'=>'C', 'ç'=>'c', 'Œ'=>'OE', 'œ'=>'oe', 'ß'=>'ss', 'Ø'=>'O', 'ø'=>'o' | |
); | |
return strtr($str, $SpecialVowels); | |
} | |
/** | |
* Check if given directory exists. If not, try to create it. | |
* @access private | |
* @param string $dir Path to the directory. | |
* @return boolean Returns (boolean) TRUE if directory exists, | |
* or was created, or FALSE if creating non-existing | |
* directory failed. | |
*/ | |
private function valid_dir($dir) | |
{ | |
if(is_dir($dir) !== FALSE) { | |
chmod($dir, 0777); # Ensure permissions. Otherwise CURLOPT_FILE will fail! | |
return TRUE; | |
} | |
else { | |
return (bool) ! @mkdir($dir, 0777); | |
} | |
} | |
/** | |
* Check on the command line if we can find an Ffmpeg installation on the script host. | |
* @access private | |
* @return boolean Returns (boolean) TRUE if Ffmpeg is installed on the server, | |
* or FALSE if not. | |
*/ | |
private function has_ffmpeg() | |
{ | |
$sh = 'which /usr/local/bin/ffmpeg'; | |
return (bool) (strlen(trim($sh)) > 0); | |
} | |
/** | |
* HTTP HEAD request with curl. | |
* @access private | |
* @param string $url String, containing the URL to curl. | |
* @return intval Returns a HTTP status code. | |
*/ | |
private function curl_httpstatus($url) | |
{ | |
$ch = curl_init($url); | |
curl_setopt($ch, CURLOPT_USERAGENT, $this->CURL_UA); | |
curl_setopt($ch, CURLOPT_REFERER, $this->YT_BASE_URL); | |
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); | |
curl_setopt($ch, CURLOPT_NOBODY, 1); | |
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5); | |
$str = curl_exec($ch); | |
$int = curl_getinfo($ch, CURLINFO_HTTP_CODE); | |
curl_close($ch); | |
return intval($int); | |
} | |
/** | |
* HTTP GET request with curl. | |
* @access private | |
* @param string $url String, containing the URL to curl. | |
* @return string Returns string, containing the curl result. | |
*/ | |
private function curl_get($url) | |
{ | |
$ch = curl_init($url); | |
curl_setopt($ch, CURLOPT_USERAGENT, $this->CURL_UA); | |
curl_setopt($ch, CURLOPT_REFERER, $this->YT_BASE_URL); | |
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); | |
$contents = curl_exec ($ch); | |
curl_close ($ch); | |
return $contents; | |
} | |
/** | |
* HTTP GET request with curl that writes the curl result into a local file. | |
* @access private | |
* @param string $remote_file String, containing the remote file URL to curl. | |
* @param string $local_file String, containing the path to the file to save | |
* the curl result in to. | |
* @return void | |
*/ | |
private function curl_get_file($remote_file, $local_file) | |
{ | |
$ch = curl_init($remote_file); | |
curl_setopt($ch, CURLOPT_USERAGENT, $this->CURL_UA); | |
curl_setopt($ch, CURLOPT_REFERER, $this->YT_BASE_URL); | |
$fp = fopen($local_file, 'w'); | |
curl_setopt($ch, CURLOPT_FILE, $fp); | |
curl_exec ($ch); | |
curl_close ($ch); | |
fclose($fp); | |
} | |
// Getter and Setter for the downloaded audio file. | |
public function get_audio() { | |
return $this->audio; } | |
private function set_audio($audio) { | |
$this->audio = $audio; } | |
// Getter and Setter for the downloaded video file. | |
public function get_video() { | |
return $this->video; } | |
private function set_video($video) { | |
$this->video = $video; } | |
// Getter and Setter for the downloaded video preview image. | |
public function get_thumb() { | |
return $this->thumb; } | |
private function set_thumb($img) { | |
if(is_string($img)) { | |
$this->thumb = $img; | |
} else { | |
throw new Exception("Invalid thumbnail given: $img"); } | |
} | |
// Getter and Setter whether to download the video, or convert to audio by default. | |
public function get_default_download() { | |
return $this->defaultDownload; } | |
public function set_default_download($action) { | |
if($action == "audio" || $action == "video") { | |
$this->defaultDownload = $action; | |
} else { | |
throw new Exception("Invalid download type. Must be either 'audio', or 'video'."); } | |
} | |
// Getter and Setter for the video quality. | |
public function get_video_quality() { | |
return $this->videoQuality; } | |
public function set_video_quality($q) { | |
if(in_array($q, array(0,1))) { | |
$this->videoQuality = $q; | |
} else { | |
throw new Exception("Invalid video quality."); } | |
} | |
// Getter and Setter for the audio quality. | |
public function get_audio_quality() { | |
return $this->audioQuality; } | |
public function set_audio_quality($q) { | |
if($q >= 128 && $q <= 320) { | |
$this->audioQuality = $q; | |
} else { | |
throw new Exception("Audio sample rate must be between 128 and 320."); } | |
} | |
// Getter and Setter for the audio output filetype. | |
public function get_audio_format() { | |
return $this->audioFormat; } | |
public function set_audio_format($ext) { | |
$valid_exts = array("mp3", "wav", "ogg", "mp4"); | |
if(in_array($ext, $valid_exts)) { | |
$this->audioFormat = $ext; | |
} else { | |
throw new Exception("Invalid audio filetype '$ext' defined. | |
Valid filetypes are: " . implode(", ", $valid_exts) ); } | |
} | |
// Getter and Setter for the download directory. | |
public function get_downloads_dir() { | |
return $this->downloadsDir; } | |
public function set_downloads_dir($dir) { | |
if(self::valid_dir($dir) !== FALSE) { | |
$this->downloadsDir = $dir; | |
} else { | |
throw new Exception("Can neither find, nor create download folder: $dir"); } | |
} | |
// Getter and Setter whether to log Ffmpeg processes. | |
public function get_ffmpegLogs_active() { | |
return $this->FfmpegLogsDir; } | |
public function set_ffmpegLogs_active($b) { | |
$this->FfmpegLogsActive = (bool) ($b !== FALSE); } | |
// Getter and Setter for the YouTube URL map. | |
public function get_yt_url_map() { | |
return $this->downloadsArray; } | |
private function set_yt_url_map($videos) { | |
$this->downloadsArray = $videos; } | |
// Getter and Setter for the YouTube Video-ID. | |
public function get_video_id() { | |
return $this->videoID; } | |
public function set_video_id($id) { | |
if(strlen($id) == 11) { | |
$this->videoID = $id; | |
} else { | |
throw new Exception("$id is not a valid Youtube Video ID."); } | |
} | |
// Getter and Setter for the formatted video title. | |
public function get_video_title() { | |
return $this->videoTitle; } | |
public function set_video_title($str) { | |
if(is_string($str)) { | |
$this->videoTitle = $str; | |
} else { | |
throw new Exception("Invalid title given: $str"); } | |
} | |
// Getter and Setter for thumbnail preferences. | |
public function get_download_thumbnail() { | |
return $this->downloadThumbs; } | |
public function set_download_thumbnail($q) { | |
if($q == TRUE || $q == FALSE) { | |
$this->downloadThumbs = (bool) $q; | |
} else { | |
throw new Exception("Invalid argument given to set_download_thumbnail."); } | |
} | |
// Getter and Setter for the video preview image size. | |
public function get_thumb_size() { | |
return $this->videoThumbSize; } | |
public function set_thumb_size($s) { | |
if($s == "s") { | |
$this->videoThumbSize = "default"; } | |
else if($s == "l") { | |
$this->videoThumbSize = "hqdefault"; } | |
else { | |
throw new Exception("Invalid thumbnail size specified."); } | |
} | |
// Getter and Setter for the object's Ffmpeg log file. | |
public function get_ffmpeg_Logfile() { | |
return $this->ffmpegLogfile; } | |
private function set_ffmpeg_Logfile($str) { | |
$this->ffmpegLogfile = $str; } | |
// Getter and Setter for the remote video preview image. | |
public function get_video_thumb() { | |
return $this->videoThumb; } | |
private function set_video_thumb($img) { | |
$this->videoThumb = $img; } | |
// Getter and Setter for the Ffmpeg-Logs directory. | |
public function get_ffmpegLogs_dir() { | |
return $this->FfmpegLogsDir; } | |
public function set_ffmpegLogs_dir($dir) { | |
if(self::valid_dir($dir) !== FALSE) { | |
$this->FfmpegLogsDir = $dir; | |
} else { | |
throw new Exception("Can neither find, nor create ffmpeg log directory '$dir', but logging is enabled."); } | |
} | |
/** | |
* Format file size in bytes into human-readable string. | |
* @access public | |
* @param string $bytes Filesize in bytes. | |
* @return string Returns human-readable formatted filesize. | |
*/ | |
public function human_bytes($bytes) | |
{ | |
$fsize = $bytes; | |
switch ($bytes): | |
case $bytes < 1024: | |
$fsize = $bytes .' B'; break; | |
case $bytes < 1048576: | |
$fsize = round($bytes / 1024, 2) .' KiB'; break; | |
case $bytes < 1073741824: | |
$fsize = round($bytes / 1048576, 2) . ' MiB'; break; | |
case $bytes < 1099511627776: | |
$fsize = round($bytes / 1073741824, 2) . ' GiB'; break; | |
endswitch; | |
return $fsize; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment