Subversion Repositories yt_downloader

Rev

Rev 14 | Rev 16 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 14 Rev 15
Line 1... Line 1...
1
#!/usr/bin/php
1
#!/usr/bin/php
2
<?php
2
<?php
3
 
3
 
4
// ViaThinkSoft YouTube Downloader Util 2.3
4
// ViaThinkSoft YouTube Downloader Util 2.3
5
// Revision: 2022-02-06
5
// Revision: 2022-02-07
6
// Author: Daniel Marschall <www.daniel-marschall.de>
6
// Author: Daniel Marschall <www.daniel-marschall.de>
7
// Licensed under the terms of the Apache 2.0 License
7
// Licensed under the terms of the Apache 2.0 License
8
//
8
//
9
// For syntax and other documentation, please read the file README.
9
// For syntax and other documentation, please read the file README.
10
 
10
 
Line 489... Line 489...
489
		if ($verbose) echo "Downloading '$title' as ".hf_type($type)." ...\n";
489
		if ($verbose) echo "Downloading '$title' as ".hf_type($type)." ...\n";
490
		ytdwn_video_id($id);
490
		ytdwn_video_id($id);
491
	}
491
	}
492
}
492
}
493
 
493
 
-
 
494
function template_to_wildcard($template, $video_id) {
-
 
495
	$x = $template;
-
 
496
	$x = str_replace('%(id)s', $video_id, $x);
-
 
497
	$x = preg_replace('@%\\(.+\\)s@ismU', '*', $x);
-
 
498
	$x = preg_replace('@\\*+@', '*', $x);
-
 
499
	return $x;
-
 
500
}
-
 
501
 
-
 
502
function ytdwn_get_downloaded_filename($outputTemplate, $video_id) {
-
 
503
	if (strpos($outputTemplate, '%(id)s') === false) {
-
 
504
		// TODO: There needs to be a better way to find out the written file name !!!
-
 
505
		return false;
-
 
506
	} else {
-
 
507
		$wildcard = template_to_wildcard($outputTemplate, $video_id);
-
 
508
		$test = glob($wildcard);
-
 
509
		if (count($test) == 0) return false;
-
 
510
		return $test[0];
-
 
511
	}
-
 
512
}
-
 
513
 
494
function ytdwn_video_id($video_id) {
514
function ytdwn_video_id($video_id) {
495
	global $type;
515
	global $type;
496
	global $verbose;
516
	global $verbose;
497
	global $mp3id_transfer;
517
	global $mp3id_transfer;
498
	global $extra_args;
518
	global $extra_args;
Line 526... Line 546...
526
		if (!empty($format)) {
546
		if (!empty($format)) {
527
			exec(YTDL_EXE.' -o '.escapeshellarg($outputTemplate).' '.$extra_args.(empty($cookie_file) ? '' : ' --cookies '.$cookie_file).' '.escapeshellarg(vid_to_vurl($video_id)).' --format '.escapeshellarg($format), $out, $code);
547
			exec(YTDL_EXE.' -o '.escapeshellarg($outputTemplate).' '.$extra_args.(empty($cookie_file) ? '' : ' --cookies '.$cookie_file).' '.escapeshellarg(vid_to_vurl($video_id)).' --format '.escapeshellarg($format), $out, $code);
528
		} else {
548
		} else {
529
			exec(YTDL_EXE.' -o '.escapeshellarg($outputTemplate).' '.$extra_args.(empty($cookie_file) ? '' : ' --cookies '.$cookie_file).' '.escapeshellarg(vid_to_vurl($video_id)), $out, $code);
549
			exec(YTDL_EXE.' -o '.escapeshellarg($outputTemplate).' '.$extra_args.(empty($cookie_file) ? '' : ' --cookies '.$cookie_file).' '.escapeshellarg(vid_to_vurl($video_id)), $out, $code);
530
		}
550
		}
-
 
551
 
-
 
552
		$written_file = $code == 0 ? ytdwn_get_downloaded_filename($outputTemplate, $video_id) : false;
-
 
553
 
531
	} else if (substr($type,0,2) == 'a:') {
554
	} else if (substr($type,0,2) == 'a:') {
532
		$format = substr($type,2);
555
		$format = substr($type,2);
533
		if (!empty($format)) {
556
		if (!empty($format)) {
534
			exec(YTDL_EXE.' -o '.escapeshellarg($outputTemplate).' '.$extra_args.(empty($cookie_file) ? '' : ' --cookies '.$cookie_file).' '.escapeshellarg(vid_to_vurl($video_id)).' --extract-audio --audio-format '.escapeshellarg($format), $out, $code);
557
			exec(YTDL_EXE.' -o '.escapeshellarg($outputTemplate).' '.$extra_args.(empty($cookie_file) ? '' : ' --cookies '.$cookie_file).' '.escapeshellarg(vid_to_vurl($video_id)).' --extract-audio --audio-format '.escapeshellarg($format), $out, $code);
535
		} else {
558
		} else {
536
			exec(YTDL_EXE.' -o '.escapeshellarg($outputTemplate).' '.$extra_args.(empty($cookie_file) ? '' : ' --cookies '.$cookie_file).' '.escapeshellarg(vid_to_vurl($video_id)).' --extract-audio', $out, $code);
559
			exec(YTDL_EXE.' -o '.escapeshellarg($outputTemplate).' '.$extra_args.(empty($cookie_file) ? '' : ' --cookies '.$cookie_file).' '.escapeshellarg(vid_to_vurl($video_id)).' --extract-audio', $out, $code);
537
		}
560
		}
-
 
561
 
-
 
562
		$written_file = $code == 0 ? ytdwn_get_downloaded_filename($outputTemplate, $video_id) : false;
-
 
563
 
538
		if (($mp3id_transfer) && ($format == 'mp3')) mp3_transfer_vid_to_id();
564
		if (($code == 0) && ($mp3id_transfer) && (strtolower($format) == 'mp3')) {
-
 
565
			if ($written_file === false) {
-
 
566
				fwrite(STDERR, "Cannot include YouTube ID to MP3, because the default template does not contain '%(id)s', or the downloaded file could not be determined for another reason.\n");
-
 
567
			} else {
-
 
568
				mp3_transfer_vid_to_id($written_file, $video_id);
-
 
569
			}
-
 
570
		}
-
 
571
	} else {
539
	} else assert(false);
572
		assert(false);
-
 
573
		return false;
-
 
574
	}
540
 
575
 
541
	if ($code == 0) {
576
	if ($code == 0) {
-
 
577
		if ($verbose) {
542
		if ($verbose) fwrite(STDOUT, "Successfully downloaded video ID $video_id as ".hf_type($type)."\n");
578
			fwrite(STDOUT, "Successfully downloaded video ID $video_id as ".hf_type($type)."\n");
-
 
579
			if ($written_file !== false) fwrite(STDOUT, "Output file name: $written_file\n");
-
 
580
		}
543
		if (!empty(_getAlreadyDownloaded())) {
581
		if (!empty(_getAlreadyDownloaded())) {
544
			try {
582
			try {
545
				addto_alreadydownloaded_file($type, $video_id);
583
				addto_alreadydownloaded_file($type, $video_id);
546
			} catch(Exception $e) {
584
			} catch(Exception $e) {
547
				fwrite(STDERR, "Cannot add to 'already downloaded' file\n");
585
				fwrite(STDERR, "Cannot add to 'already downloaded' file\n");
548
			}
586
			}
549
		}
587
		}
550
 
588
 
551
		// Now do the checksums
589
		// Now do the checksums
552
		foreach (explode(',',$checksumMode) as $mode) {
590
		foreach (explode(',',$checksumMode) as $mode) {
553
			$test = glob(rtrim(_getOutputDir(), '/').'/*-'.$video_id.'.*');
591
			if (strtolower($mode) === 'none') continue;
554
			if (count($test) == 0) {
592
			if ($written_file === false) {
555
				fwrite(STDERR, "Cannot determine output file name.\n");
593
				fwrite(STDERR, "Cannot add to the '$mode' checksum file, because the default template does not contain '%(id)s', or the downloaded file could not be determined for another reason.\n");
556
			}
-
 
557
			$written_file = $test[0];
-
 
558
			if (!cs_add_automatically($written_file, $mode)) {
594
			} else if (!cs_add_automatically($written_file, $mode)) {
559
				fwrite(STDERR, "Could not write to '$mode' checksum file!\n");
595
				fwrite(STDERR, "Could not write to '$mode' checksum file!\n");
560
			}
596
			}
561
		}
597
		}
562
	} else {
598
	} else {
563
		fwrite(STDERR, "Error downloading $video_id! (Code $code)\n");
599
		fwrite(STDERR, "Error downloading $video_id! (Code $code)\n");
Line 580... Line 616...
580
 
616
 
581
function EndsWith($Haystack, $Needle){
617
function EndsWith($Haystack, $Needle){
582
	return strrpos($Haystack, $Needle) === strlen($Haystack)-strlen($Needle);
618
	return strrpos($Haystack, $Needle) === strlen($Haystack)-strlen($Needle);
583
}
619
}
584
 
620
 
585
function mp3_transfer_vid_to_id() {
621
function mp3_transfer_vid_to_id(&$written_file, $video_id) {
586
	global $verbose;
622
	global $verbose;
587
	global $default_template;
623
	global $default_template;
588
 
624
 
589
	if (!command_exists('id3v2')) {
625
	if (!command_exists('id3v2')) {
590
		if ($verbose) echo "Note: Tool id3v2 is not installed. Will not transfer the YouTube ID into the MP3 ID Tag\n";
626
		fwrite(STDERR, "Tool id3v2 is not installed. Will not transfer the YouTube ID into the MP3 ID Tag. Use paramter '-N' to stop trying the transfer.\n");
591
		return false;
627
		return false;
592
	}
628
	}
593
 
629
 
594
	if (!EndsWith($default_template, '-%(id)s.%(ext)s'))  {
630
	$orig_ts = filemtime($written_file);
-
 
631
	$ec = -1;
595
		if ($verbose) echo "Note: Cannot transfer video tag to MP3 because default template does not end with '-%(id)s.%(ext)s'.\n";
632
	system('id3v2 -c '.escapeshellarg($video_id).' '.escapeshellarg($written_file), $ec);
-
 
633
	touch($written_file, $orig_ts);
-
 
634
	if ($ec != 0) {
-
 
635
		fwrite(STDERR, "Cannot set ID tag for file $written_file\n");
596
		return false;
636
		return false;
597
	}
637
	}
598
 
638
 
599
	$allok = true;
-
 
600
	$files = glob(rtrim(_getOutputDir(), '/').'/*-???????????.mp3');
-
 
601
	foreach ($files as $filename) {
639
	$target_filename = $written_file;
602
		$m = null;
-
 
603
		if (!preg_match('@-([a-zA-Z0-9\-_]{11})\.mp3$@ismU', $filename, $m)) continue;
-
 
604
		$yt_id = $m[1];
-
 
605
 
-
 
606
		if (!yt_check_video_id($yt_id)) continue; // just to be sure
-
 
607
 
640
 
-
 
641
	// Things like '<title>-<id>.mp3' become '<title>.mp3' (our default template)
-
 
642
	// But templates like '<title> (<id>).mp3' could become '<title> ().mp3', which is not nice
-
 
643
	// So, we try our best to find the most common template types...
608
		$orig_ts = filemtime($filename);
644
	$target_filename = str_replace('-'.$video_id, '', $target_filename);
609
		$ec = -1;
645
	$target_filename = str_replace('_'.$video_id, '', $target_filename);
-
 
646
	$target_filename = str_replace(' '.$video_id, '', $target_filename);
610
		system('id3v2 -c '.escapeshellarg($yt_id).' '.escapeshellarg($filename), $ec);
647
	$target_filename = str_replace('('.$video_id.')', '', $target_filename);
611
		touch($filename, $orig_ts);
648
	$target_filename = str_replace('['.$video_id.']', '', $target_filename);
-
 
649
	$target_filename = str_replace($video_id, '', $target_filename); // must be the last!
612
		if ($ec != 0) {
650
	if ($target_filename === $written_file) {
613
			fwrite(STDERR, "Cannot set ID tag for file $filename\n");
651
		fwrite(STDERR, "Could not remove VideoID from filename '$written_file'\n"); // should not happen
614
			$allok = false;
652
		return false;
615
			continue;
-
 
616
		}
653
	}
617
 
654
 
618
		$target_filename = str_replace("-$yt_id.mp3", '.mp3', $filename);
-
 
619
		if (!intelligent_rename($filename, $target_filename)) {
655
	if (!intelligent_rename($written_file, $target_filename)) {
620
			fwrite(STDERR, "Cannot move file $filename to $target_filename\n");
656
		fwrite(STDERR, "Could not rename '$written_file' to '$target_filename'\n");
621
			$allok = false;
657
		return false;
622
			continue;
-
 
623
		}
-
 
624
	}
658
	}
-
 
659
 
-
 
660
	$written_file = $target_filename; // was modified by intelligent_rename()
625
	return $allok;
661
	return true;
626
}
662
}
627
 
663
 
628
function curl_to_cid($channel_url) {
664
function curl_to_cid($channel_url) {
629
	return yt_get_channel_id_from_url($channel_url);
665
	return yt_get_channel_id_from_url($channel_url);
630
}
666
}
Line 877... Line 913...
877
	} else {
913
	} else {
878
		return 0;
914
		return 0;
879
	}
915
	}
880
}
916
}
881
 
917
 
882
function intelligent_rename($src, $dest) {
918
function intelligent_rename($src, &$dest) {
883
	$pos = strrpos($dest, '.');
919
	$pos = strrpos($dest, '.');
884
	$ext = substr($dest, $pos);
920
	$ext = substr($dest, $pos);
885
	$namewoext = substr($dest, 0, $pos);
921
	$namewoext = substr($dest, 0, $pos);
886
	$failcnt = 1;
922
	$failcnt = 1;
887
	$dest_neu = $dest;
923
	$dest_neu = $dest;
888
	while (file_exists($dest_neu)) {
924
	while (file_exists($dest_neu)) {
889
		$failcnt++;
925
		$failcnt++;
890
		$dest_neu = "$namewoext ($failcnt)$ext";
926
		$dest_neu = "$namewoext ($failcnt)$ext";
891
	}
927
	}
892
	return rename($src, $dest_neu);
928
	$res = rename($src, $dest_neu);
-
 
929
	if ($res) $dest = $dest_neu;
-
 
930
	return $res;
893
}
931
}
894
 
932
 
895
function get_latest_ytdl_md5sum() {
933
function get_latest_ytdl_md5sum() {
896
	$ch = curl_init();
934
	$ch = curl_init();
897
	curl_setopt($ch, CURLOPT_URL, 'https://yt-dl.org/downloads/latest/MD5SUMS');
935
	curl_setopt($ch, CURLOPT_URL, 'https://yt-dl.org/downloads/latest/MD5SUMS');