Guest User

Record YouTube streams

a guest
Jul 22nd, 2019
284
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. INSTALLATION (Windows)
  2. 1. Install streamlink: https://github.com/streamlink/streamlink
  3. 2. Install PHP 7 and make sure .php files are opened by php.exe. If you don't know what you're doing, XAMPP should install everything properly: https://www.apachefriends.org/download.html
  4. 3. Copy the code below into a file named whatever.php in notepad. Adjust the first two lines ($dir and $format) to specify the directory to save files and the default format.
  5.  
  6. USAGE
  7. 4. Run whatever.php, paste the video URL in the command line that opens and press enter. It will start recording to the directory you specified.
  8.  
  9.  
  10.  
  11.  
  12.  
  13.  
  14.  
  15.  
  16.  
  17.  
  18.  
  19.  
  20.  
  21. <?php
  22. $dir = 'C:/Users/K/Videos'; # directory to save video
  23. $format = '720p'; # default format
  24.  
  25. echo 'Enter URL: ';
  26. $url = trim(fgets(STDIN));
  27. $args = explode(' ', $url);
  28. $url = explode('&', $args[0])[0]; # Remove stuff after &
  29. /* There are a few arguments that you can optionally add after the URL (no hyphens):
  30.    480/720/1080 : Choose a non-default format.
  31.    p (play) : Open the video in VLC.
  32.    q (quick) : Use an ugly filename instead of spending a second fetching the meta info.
  33.    For example, you could type:
  34.      https://www.youtube.com/watch?v=sEYzlLfLn-Y 1080 q p
  35.    To record that video in 1080p, play it in VLC and use an ugly filename.
  36. */
  37.  
  38. # If the URL is a /channel/.../live style URL, get the video URL.
  39. if(strpos($url, '/live') !== false) {
  40.     $page = file_get_contents($url);
  41.     preg_match('!"video_id":"(.*?)"!', $page, $matches);
  42.     if(empty($matches[1])) {
  43.         exit("Could not get real video URL.\n");
  44.     }
  45.     $url = 'https://www.youtube.com/watch?v=' . $matches[1];
  46. }
  47.  
  48. # Format: 480, 720 or 1080
  49. foreach(array('480', '720', '1080') as $option) {
  50.     if(in_array($option, $args)) {
  51.         $format = $option . 'p';
  52.     }
  53. }
  54.  
  55. # Play in VLC only if "play" or "p" is present in the arguments
  56. $play = 'output';
  57. if(in_array('play', $args) || in_array('p', $args)) {
  58.     $play = 'record';
  59. }
  60.  
  61. # Get video title and author.
  62. function get_meta_info($url) {
  63.     # Alternative: https://www.youtube.com/oembed?url=https://www.youtube.com/watch?v=lUOhCtXPN40&format=json
  64.     $info = json_decode(file_get_contents('https://noembed.com/embed?url=' . urlencode($url)), true);
  65.     $return = array();
  66.     if( ! empty($info['title'])) {
  67.         $return['title'] = $info['title'];
  68.         $return['author'] = $info['author_name'];
  69.     }
  70.     else if(isset($info['error']) && $info['error'] == '401 Unauthorized') {
  71.         # Embedding disabled. Fetch the info through a slightly slower method.
  72.         $page = file_get_contents($url);
  73.         preg_match('!"title":"(.*?)"!', $page, $matches);
  74.         if( ! empty($matches[1])) {
  75.             $return['title'] = stripslashes($matches[1]);
  76.             preg_match('!"author":"(.*?)"!', $page, $matches);
  77.             $return['author'] = stripslashes($matches[1]);
  78.         }
  79.     }
  80.     return $return;
  81. }
  82.  
  83. # Fetch full title for filename if "quick" and "q" are not present
  84. $code = explode('=', $url)[1];
  85. $title = date('Y-m-d H.i.s') . ' ' . $code;
  86. if( ! in_array('quick', $args) && ! in_array('q', $args)) {
  87.     $info = get_meta_info($url);
  88.     if(empty($info)) {
  89.         echo "Failed to fetch info.\n";
  90.     } else {
  91.         echo "Retrieved meta info.\n";
  92.         $video_title = $info['title'];
  93.         $video_author = $info['author'];
  94.         $title = date('Y-m-d') . ' - ' . $video_author . ' - ' . $video_title . ' - ' . $code . ' (' . date('H.i.s') . ')';
  95.         # Replace characters not allowed in filenames
  96.         $find = array(
  97.             '/',
  98.             '<',
  99.             '>',
  100.             ':',
  101.             '\\',
  102.             '|',
  103.             '?',
  104.             '*'
  105.         );
  106.         $replace = array(
  107.             '/',
  108.             '<',
  109.             '>',
  110.             ':',
  111.             '/',
  112.             '|',
  113.             '?',
  114.             '*'
  115.         );
  116.         $title = str_replace($find, $replace, $title);
  117.     }
  118. }
  119.  
  120. while(true) {
  121.     echo "Attempting to start recording.\n";
  122.     $response = exec('streamlink ' . $url . ' ' . $format . ' --' . $play . ' "' . $dir . '/' . $title . '.mp4"');
  123.    
  124.     # If stream hasn't started, sleep until its scheduled time. After that, reattempt every 10 seconds.
  125.     if(strpos($response, 'error: No playable streams found') !== false) {
  126.         if( ! isset($start_time)) {
  127.             $json = json_decode(file_get_contents('https://www.youtube.com/heartbeat?video_id=' . $code), true);
  128.             if(isset($json['liveStreamability']['liveStreamabilityRenderer']['offlineSlate']['liveStreamOfflineSlateRenderer']['scheduledStartTime'])) {
  129.                 $start_time = (int) $json['liveStreamability']['liveStreamabilityRenderer']['offlineSlate']['liveStreamOfflineSlateRenderer']['scheduledStartTime'];
  130.             } else {
  131.                 echo "Start timestamp not found.\n";
  132.                 break;
  133.             }
  134.         }
  135.         if(time() > $start_time) {
  136.             $start_time = time() + 10;
  137.         }
  138.         $remaining = $start_time - time();
  139.         echo "Waiting " . $remaining . " seconds...\n";
  140.         time_sleep_until($start_time);
  141.     }
  142.     else {
  143.         # Stream finished.
  144.         break;
  145.     }
  146. }
  147.  
  148. sleep(5);
Advertisement
Add Comment
Please, Sign In to add comment