Fix youtube thumbnails, add youtube-dl support
This commit is contained in:
parent
321bf99cf8
commit
3f443cbea5
|
@ -155,6 +155,7 @@ if (!$cache_loaded) {
|
|||
// ---------------------------------- Attachment handling -----------------------------------
|
||||
$cf['KU_FFMPEGPATH'] = '/usr/local/bin/ffmpeg'; //path to FFMPEG, on windows it's usually 'C:\ffmpeg\bin' (REQUIRED for videos)
|
||||
$cf['KU_YOUTUBE_APIKEY'] = 'your_api_key'; //Your personal anal probe ID. Can be obtained it Google Dev. Console
|
||||
$cf['I0_YOUTUBE_DL_PATH'] = ''; // Path to youtube-dl binary. If not empty, youtube-dl will be used instead of default API (in this case you won't need KU_YOUTUBE_APIKEY)
|
||||
$cf['KU_THUMBWIDTH'] = 200; // Maximum thumbnail width
|
||||
$cf['KU_THUMBHEIGHT'] = 200; // Maximum thumbnail height
|
||||
$cf['KU_REPLYTHUMBWIDTH'] = 125; // Maximum thumbnail width (reply)
|
||||
|
|
|
@ -91,17 +91,20 @@ function createThumbnail($name, $filename, $new_w, $new_h) {
|
|||
$system=explode(".", $filename);
|
||||
$system = array_reverse($system);
|
||||
if (preg_match("/jpg|jpeg/", $system[0])) {
|
||||
$src_img=imagecreatefromjpeg($name);
|
||||
$src_img=@imagecreatefromjpeg($name);
|
||||
} else if (preg_match("/png/", $system[0])) {
|
||||
$src_img=imagecreatefrompng($name);
|
||||
$src_img=@imagecreatefrompng($name);
|
||||
} else if (preg_match("/gif/", $system[0])) {
|
||||
$src_img=imagecreatefromgif($name);
|
||||
$src_img=@imagecreatefromgif($name);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!$src_img) {
|
||||
exitWithErrorPage(_gettext('Unable to read uploaded file during thumbnailing.'), _gettext('A common cause for this is an incorrect extension when the file is actually of a different type.'));
|
||||
// Check for the case if the image is actually wrong type
|
||||
list($src_img, $actual_type)=imagecreatefromwhatever($name);
|
||||
if (!$src_img)
|
||||
exitWithErrorPage(_gettext('Unable to read uploaded file during thumbnailing.'), _gettext('A common cause for this is an incorrect extension when the file is actually of a different type.'));
|
||||
}
|
||||
$old_x = imageSX($src_img);
|
||||
$old_y = imageSY($src_img);
|
||||
|
@ -116,7 +119,18 @@ function createThumbnail($name, $filename, $new_w, $new_h) {
|
|||
$dst_img = ImageCreateTrueColor($thumb_w, $thumb_h);
|
||||
fastImageCopyResampled($dst_img, $src_img, 0, 0, 0, 0, $thumb_w, $thumb_h, $old_x, $old_y, $system);
|
||||
|
||||
if (preg_match("/png/", $system[0])) {
|
||||
if ($actual_type) {
|
||||
if (($actual_type == 'jpg' || $actual_type == 'webp') && !imagejpeg($dst_img, $filename, 70)) {
|
||||
exitWithErrorPage('unable to imagejpg.');
|
||||
return false;
|
||||
} else if ($actual_type == 'png' && !imagepng($dst_img,$filename,0,PNG_ALL_FILTERS)) {
|
||||
exitWithErrorPage('unable to imagepng.');
|
||||
return false;
|
||||
} else if ($actual_type == 'gif' && !imagegif($dst_img, $filename)) {
|
||||
exitWithErrorPage('unable to imagegif.');
|
||||
return false;
|
||||
}
|
||||
} else if (preg_match("/png/", $system[0])) {
|
||||
if (!imagepng($dst_img,$filename,0,PNG_ALL_FILTERS) ) {
|
||||
exitWithErrorPage('unable to imagepng.');
|
||||
return false;
|
||||
|
@ -142,6 +156,27 @@ function createThumbnail($name, $filename, $new_w, $new_h) {
|
|||
return false;
|
||||
}
|
||||
|
||||
// Sometimes the image is of wrong type, particularly thumbnails from Youtube
|
||||
function imagecreatefromwhatever($fname) {
|
||||
if ($img = @imagecreatefromjpeg($fname)) {
|
||||
$type = 'jpg';
|
||||
return array($img, $type);
|
||||
}
|
||||
if ($img = @imagecreatefromwebp($fname)) {
|
||||
$type = 'webp';
|
||||
return array($img, $type);
|
||||
}
|
||||
if ($img = @imagecreatefrompng($fname)) {
|
||||
$type = 'png';
|
||||
return array($img, $type);
|
||||
}
|
||||
if ($img = @imagecreatefromgif($fname)) {
|
||||
$type = 'gif';
|
||||
return array($img, $type);
|
||||
}
|
||||
return array(false, false);
|
||||
}
|
||||
|
||||
/* Author: Tim Eckel - Date: 12/17/04 - Project: FreeRingers.net - Freely distributable. */
|
||||
/**
|
||||
* Faster method than only calling imagecopyresampled()
|
||||
|
@ -210,94 +245,127 @@ function fetch_video_data($site, $code, $maxwidth, $thumb_tmpfile) {
|
|||
if (!in_array($site, array('you', 'vim', 'cob', 'scl')))
|
||||
return array('error' => 'unsupported_site');
|
||||
|
||||
$use_youtube_dl = I0_YOUTUBE_DL_PATH !== '' && $site === 'you';
|
||||
|
||||
// Pre-setup
|
||||
$ch = curl_init();
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
|
||||
curl_setopt ($ch, CURLOPT_TIMEOUT, 10);
|
||||
if (I0_CURL_PROXY)
|
||||
curl_setopt($ch, CURLOPT_PROXY, I0_CURL_PROXY);
|
||||
|
||||
// Getting a URL
|
||||
switch ($site) {
|
||||
case 'cob':
|
||||
$url = "https://coub.com/api/v2/coubs/".$code.".json";
|
||||
break;
|
||||
case 'vim':
|
||||
$url = 'https://vimeo.com/api/v2/video/'.$code.'.json';
|
||||
break;
|
||||
case 'you':
|
||||
$url = 'https://www.googleapis.com/youtube/v3/videos?part=contentDetails%2Csnippet&id='.$code.'&key='.KU_YOUTUBE_APIKEY;
|
||||
break;
|
||||
case 'scl':
|
||||
$url = 'https://soundcloud.com/oembed?url=https%3A%2F%2Fsoundcloud.com%2F' . urlencode($code) . '&format=json';
|
||||
break;
|
||||
default:
|
||||
return array('error' => _gettext('No JSON URL specified.'));
|
||||
if ($use_youtube_dl) {
|
||||
putenv('PATH=' . I0_YOUTUBE_DL_PATH . PATH_SEPARATOR . getenv('PATH'));
|
||||
}
|
||||
curl_setopt($ch, CURLOPT_URL, $url);
|
||||
|
||||
// Fetching data
|
||||
$result = curl_exec($ch);
|
||||
switch (curl_getinfo($ch, CURLINFO_HTTP_CODE)) {
|
||||
case 404: return array('error' => _gettext('Unable to connect to')); break;
|
||||
case 303: return array('error' => _gettext('Invalid video ID.')); break;
|
||||
case 302: break;
|
||||
case 301: break;
|
||||
case 200: break;
|
||||
default: return array('error' => _gettext('Invalid response code ').' (JSON)'); break;
|
||||
else {
|
||||
$ch = curl_init();
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
|
||||
curl_setopt ($ch, CURLOPT_TIMEOUT, 10);
|
||||
if (I0_CURL_PROXY)
|
||||
curl_setopt($ch, CURLOPT_PROXY, I0_CURL_PROXY);
|
||||
}
|
||||
|
||||
// Fetching the data
|
||||
if ($use_youtube_dl) {
|
||||
exec('youtube-dl --dump-json https://www.youtube.com/watch?v='.$code, $json, $er);
|
||||
if (!$er) {
|
||||
$ydl_info = json_decode($json[0]);
|
||||
}
|
||||
else {
|
||||
return array('error' => _gettext('API returned invalid data.'));
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Getting a URL
|
||||
switch ($site) {
|
||||
case 'cob':
|
||||
$url = "https://coub.com/api/v2/coubs/".$code.".json";
|
||||
break;
|
||||
case 'vim':
|
||||
$url = 'https://vimeo.com/api/v2/video/'.$code.'.json';
|
||||
break;
|
||||
case 'you':
|
||||
$url = 'https://www.googleapis.com/youtube/v3/videos?part=contentDetails%2Csnippet&id='.$code.'&key='.KU_YOUTUBE_APIKEY;
|
||||
break;
|
||||
case 'scl':
|
||||
$url = 'https://soundcloud.com/oembed?url=https%3A%2F%2Fsoundcloud.com%2F' . urlencode($code) . '&format=json';
|
||||
break;
|
||||
default:
|
||||
return array('error' => _gettext('No JSON URL specified.'));
|
||||
}
|
||||
curl_setopt($ch, CURLOPT_URL, $url);
|
||||
|
||||
// Fetching data
|
||||
$result = curl_exec($ch);
|
||||
switch (curl_getinfo($ch, CURLINFO_HTTP_CODE)) {
|
||||
case 404: return array('error' => _gettext('Unable to connect to')); break;
|
||||
case 303: return array('error' => _gettext('Invalid video ID.')); break;
|
||||
case 302: break;
|
||||
case 301: break;
|
||||
case 200: break;
|
||||
default: return array('error' => _gettext('Invalid response code ').' (JSON)'); break;
|
||||
}
|
||||
curl_close($ch);
|
||||
$data = json_decode($result, true);
|
||||
if ($data == NULL)
|
||||
return array('error' => _gettext('API returned invalid data.'));
|
||||
}
|
||||
curl_close($ch);
|
||||
$data = json_decode($result, true);
|
||||
if ($data == NULL)
|
||||
return array('error' => _gettext('API returned invalid data.'));
|
||||
|
||||
// Find needed thumbnail width
|
||||
switch ($site) {
|
||||
case 'cob':
|
||||
$widths_available = array(
|
||||
if ($use_youtube_dl) {
|
||||
$options_available = count($ydl_info->thumbnails);
|
||||
$i = 0;
|
||||
foreach($ydl_info->thumbnails as &$thumb) {
|
||||
$i++;
|
||||
if ($thumb->width >= $maxwidth || $options_available == $i) {
|
||||
$thumb_url = $thumb->url;
|
||||
$thumbwidth = $thumb->width;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
switch ($site) {
|
||||
case 'cob':
|
||||
$widths_available = array(
|
||||
'micro' => 70,
|
||||
'tiny' => 112,
|
||||
'small' => 400,
|
||||
'med' => 640,
|
||||
'big' => 1280
|
||||
);
|
||||
break;
|
||||
case 'vim':
|
||||
$widths_available = array(
|
||||
);
|
||||
break;
|
||||
case 'vim':
|
||||
$widths_available = array(
|
||||
'small' => 100,
|
||||
'medium' => 200,
|
||||
'large' => 640
|
||||
);
|
||||
break;
|
||||
case 'you':
|
||||
$widths_available = array(
|
||||
);
|
||||
break;
|
||||
case 'you':
|
||||
$widths_available = array(
|
||||
'default' => 120,
|
||||
'medium' => 320,
|
||||
'high' => 480,
|
||||
'standard' => 640,
|
||||
'maxres' => 1280
|
||||
);
|
||||
break;
|
||||
case 'scl':
|
||||
$widths_available = array(
|
||||
);
|
||||
break;
|
||||
case 'scl':
|
||||
$widths_available = array(
|
||||
'default' => 250
|
||||
);
|
||||
break;
|
||||
default:
|
||||
return array('error' => _gettext('No thumbnails available.'));
|
||||
}
|
||||
$i = 0;
|
||||
$options_available = count($widths_available);
|
||||
foreach ($widths_available as $preset => $width) {
|
||||
$i++;
|
||||
if ($width >= $maxwidth || $options_available == $i) {
|
||||
$chosen_preset = $preset;
|
||||
$thumbwidth = $width;
|
||||
break;
|
||||
);
|
||||
break;
|
||||
default:
|
||||
return array('error' => _gettext('No thumbnails available.'));
|
||||
}
|
||||
$i = 0;
|
||||
$options_available = count($widths_available);
|
||||
foreach ($widths_available as $preset => $width) {
|
||||
$i++;
|
||||
if ($width >= $maxwidth || $options_available == $i) {
|
||||
$chosen_preset = $preset;
|
||||
$thumbwidth = $width;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Get thumbnail URL
|
||||
switch ($site) {
|
||||
case 'cob':
|
||||
|
@ -307,7 +375,9 @@ function fetch_video_data($site, $code, $maxwidth, $thumb_tmpfile) {
|
|||
$thumb_url = preg_replace('/\.webp/', '.jpg', $data[0]['thumbnail_'.$chosen_preset]);
|
||||
break;
|
||||
case 'you':
|
||||
$thumb_url = $data['items'][0]['snippet']['thumbnails'][$chosen_preset]['url'];
|
||||
if (!$use_youtube_dl) {
|
||||
$thumb_url = $data['items'][0]['snippet']['thumbnails'][$chosen_preset]['url'];
|
||||
}
|
||||
break;
|
||||
case 'scl':
|
||||
$thumb_url = $data['thumbnail_url'];
|
||||
|
@ -356,8 +426,14 @@ function fetch_video_data($site, $code, $maxwidth, $thumb_tmpfile) {
|
|||
case 'you':
|
||||
$r['width'] = 1920;
|
||||
$r['height'] = 1080;
|
||||
$r['title'] = $data['items'][0]['snippet']['title'];
|
||||
$duration = preg_replace_callback('/PT(?:(\d+)H)?(?:(\d+)M)?(?:(\d+)S)?/', 'ISO8601_callback', $data['items'][0]['contentDetails']['duration']);
|
||||
if ($use_youtube_dl) {
|
||||
$r['title'] = $ydl_info->title;
|
||||
$duration = $ydl_info->duration;
|
||||
}
|
||||
else {
|
||||
$r['title'] = $data['items'][0]['snippet']['title'];
|
||||
$duration = preg_replace_callback('/PT(?:(\d+)H)?(?:(\d+)M)?(?:(\d+)S)?/', 'ISO8601_callback', $data['items'][0]['contentDetails']['duration']);
|
||||
}
|
||||
break;
|
||||
case 'scl':
|
||||
$r['width'] = 500;
|
||||
|
@ -371,8 +447,8 @@ function fetch_video_data($site, $code, $maxwidth, $thumb_tmpfile) {
|
|||
default:
|
||||
return array('error' => _gettext('API returned invalid data.'));
|
||||
}
|
||||
|
||||
if ($r['width'] <= 0 || $r['height'] <= 0) {
|
||||
// var_dump($r);
|
||||
return array('error' => _gettext('API returned invalid data.'));
|
||||
}
|
||||
// Convert duration into readable string
|
||||
|
|
|
@ -64,7 +64,7 @@
|
|||
// ---------------------------------- Attachment handling -----------------------------------
|
||||
$cf['KU_FFMPEGPATH'] = '/usr/local/bin/ffmpeg'; //path to FFMPEG, on windows it's usually 'C:\ffmpeg\bin' (REQUIRED for videos)
|
||||
$cf['KU_YOUTUBE_APIKEY'] = 'your_api_key'; //Your personal anal probe ID. Can be obtained it Google Dev. Console
|
||||
|
||||
$cf['I0_YOUTUBE_DL_PATH'] = ''; // Path to youtube-dl binary. If not empty, youtube-dl will be used instead of default API (in this case you won't need KU_YOUTUBE_APIKEY)
|
||||
|
||||
// ------------------------------------- Misc settings --------------------------------------
|
||||
$cf['I0_CURL_PROXY'] = false; // Proxy to use when fetching external resources, for example 'socks5h://127.0.0.1:9050' — to connect through TOR
|
||||
|
|
Loading…
Reference in New Issue