youtube_utils 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. data/bin/youtube_utils +1 -0
  2. data/lib/youtube_utils.rb +38 -37
  3. metadata +18 -44
data/bin/youtube_utils CHANGED
@@ -45,6 +45,7 @@ end
45
45
 
46
46
  def run url
47
47
  videos = YoutubeUtils.new.get_videos url
48
+ return if videos.empty?
48
49
  index = ask_user_which_one_to_download(videos).to_i
49
50
  download videos[index]['url'], build_filename(url, videos[index]['type'])
50
51
  end
data/lib/youtube_utils.rb CHANGED
@@ -1,37 +1,28 @@
1
1
  require 'net/http'
2
- require 'yajl'
3
2
  require 'uri'
4
3
 
5
4
  #http://unlockforus.blogspot.com/2010/04/downloading-youtube-videos-not-working.html
6
5
  #http://board.jdownloader.org/showthread.php?t=18520
6
+ #http://userscripts.org/topics/83095?page=1#posts-372119
7
7
  class YoutubeUtils
8
+
9
+ def initialize(debug = false)
10
+ @debug = debug
11
+ end
12
+
8
13
  def get_videos youtube_watch_url
9
14
  res = get_webpage(youtube_watch_url);
10
15
  unless res.code == '200'
11
- puts res.code
12
- return []
13
- end
14
-
15
- hash = json_to_hash(get_PLAYER_CONFIG(res.body))
16
- unless hash
17
- puts "no PLAYER_CONFIG"
18
- return []
19
- end
20
-
21
- args = hash['args']
22
- unless args
23
- puts "no args"
24
- return []
16
+ raise res.code
25
17
  end
26
18
 
27
19
  result = []
28
20
 
29
- html5_fmt_map = args['html5_fmt_map']
30
- result.concat(convert_html5_fmt_map(html5_fmt_map)) if html5_fmt_map
31
-
32
- fmt_stream_map = args['fmt_stream_map']
33
- fmt_list = args['fmt_list']
34
- result.concat(convert_fmt_stream_map(fmt_stream_map, fmt_list)) if fmt_list&&fmt_stream_map
21
+ fmt_stream_map = get_url_encoded_fmt_stream_map(res.body)
22
+ fmt_list = get_fmt_list(res.body)
23
+ puts fmt_stream_map, fmt_list if @debug
24
+
25
+ result.concat(parse_fmt_stream_map(fmt_stream_map, fmt_list)) if fmt_list&&fmt_stream_map
35
26
 
36
27
  return result
37
28
  end
@@ -60,7 +51,7 @@ class YoutubeUtils
60
51
  def convert_itag_to_type itag
61
52
  case itag.to_i
62
53
  when 0, 6
63
- return "video/flv; codecs=\" h263, mp3 mono\""
54
+ return "video/flv; codecs=\"h263, mp3 mono\""
64
55
  when 5
65
56
  return "video/flv; codecs=\"h263, mp3 stereo\""
66
57
  when 34, 35
@@ -72,35 +63,36 @@ class YoutubeUtils
72
63
  when 18, 22, 37, 38, 78
73
64
  return "video/mp4; codecs=\"h264, aac stereo\""
74
65
  when 43, 45
75
- return "video/webm; codecs=\"vp8.0, vorbis stereo\""
66
+ return "video/webm; codecs=\"vp8, vorbis stereo\""
76
67
  else
77
68
  return "unknown #{itag}"
78
69
  end
79
70
  end
80
-
81
- #{"url"=>"http://v5.lscache8.c.youtube.com/videoplayback?...", "type"=>"video/webm; codecs=\"vp8.0, vorbis\"", "itag"=>43, "quality"=>"medium"}
82
- def convert_html5_fmt_map a
83
- result = []
84
- a.each {|x|
85
- result << {'url' => x['url'], 'type' => x['type'], 'quality' => x['quality']}
71
+
72
+ def querystring_2_hash s
73
+ h = {}
74
+ s.split("\\u0026").each { |x|
75
+ a = x.split("=")
76
+ h[a[0]] = a[1]
86
77
  }
87
- return result
78
+ h
88
79
  end
89
80
 
81
+ #url=http://o-o.preferred.comcast-iad1.v2.lscache7.c.youtube.com/videoplayback?sparams=id%2Cexpire%2Cip%2Cipbits%2Citag%2Csource%2Calgorithm%2Cburst%2Cfactor%2Ccp&fexp=907508%2C903945%2C912602&algorithm=throttle-factor&itag=5&ip=69.0.0.0&burst=40&sver=3&signature=188F0E975207AB14B86050D0D21CFFFEFBCE4B00.D4BF3A75D2670F58B4FF4FF3AFADD1174A9EE574&source=youtube&expire=1324417594&key=yt1&ipbits=8&factor=1.25&cp=U0hRSVRMVV9OTkNOMV9MRllGOjdZSVc4aUgtZUFB&id=ef388a3d0169fd70\u0026quality=small\u0026fallback_host=tc.v2.cache7.c.youtube.com\u0026type=video/x-flv\u0026itag=5
90
82
  #22/1280x720/9/0/115
91
- def convert_fmt_stream_map fmt_stream_map, fmt_list
83
+ def parse_fmt_stream_map fmt_stream_map, fmt_list
92
84
  result = []
93
85
  a1 = fmt_stream_map.split(',')
94
86
  a2 = fmt_list.split(',')
95
87
  i = 0
96
88
  a1.each {|x|
97
- a11 = x.split('|')
98
- itag = a11[0]
99
- url = a11[1]
89
+ h = querystring_2_hash(x)
90
+ itag = h['itag']
91
+ url = h['url']
100
92
 
101
93
  a21 = a2[i].split('/')
102
94
  resolution = a21[1]
103
- result << {'url' => url, 'type' => convert_itag_to_type(itag), 'quality' => resolution2quality(resolution)}
95
+ result << {'url' => URI.unescape(url), 'type' => convert_itag_to_type(itag), 'quality' => resolution2quality(resolution)}
104
96
  i += 1;
105
97
  }
106
98
  return result
@@ -143,9 +135,18 @@ class YoutubeUtils
143
135
  end
144
136
  end
145
137
 
146
- def get_PLAYER_CONFIG body
147
- body[/\'PLAYER_CONFIG\':(.*)\}\)\;\n/]
138
+ def get_fmt_list body
139
+ body[/\"fmt_list\":\s?\"(.+?)\"/]
140
+ return $1
141
+ end
142
+
143
+ def get_url_encoded_fmt_stream_map body
144
+ body[/\"url_encoded_fmt_stream_map\":\s?\"(.+?)\"/]
148
145
  return $1
149
146
  end
150
147
  end
151
148
 
149
+ if __FILE__ == $0
150
+ p YoutubeUtils.new(true).get_videos "http://www.youtube.com/watch?v=7ziKPQFp_XA"
151
+ end
152
+
metadata CHANGED
@@ -1,50 +1,30 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: youtube_utils
3
3
  version: !ruby/object:Gem::Version
4
- hash: 27
5
- prerelease: false
6
- segments:
7
- - 0
8
- - 1
9
- - 0
10
- version: 0.1.0
4
+ prerelease:
5
+ version: 0.1.1
11
6
  platform: ruby
12
7
  authors:
13
- - Xue Yong Zhi
8
+ - Xue Yong Zhi
14
9
  autorequire:
15
10
  bindir: bin
16
11
  cert_chain: []
17
12
 
18
- date: 2011-04-28 00:00:00 -04:00
19
- default_executable:
20
- dependencies:
21
- - !ruby/object:Gem::Dependency
22
- name: yajl-ruby
23
- prerelease: false
24
- requirement: &id001 !ruby/object:Gem::Requirement
25
- none: false
26
- requirements:
27
- - - ">="
28
- - !ruby/object:Gem::Version
29
- hash: 3
30
- segments:
31
- - 0
32
- version: "0"
33
- type: :runtime
34
- version_requirements: *id001
13
+ date: 2011-04-28 00:00:00 Z
14
+ dependencies: []
15
+
35
16
  description:
36
17
  email:
37
- - yong@intridea.com
18
+ - yong@intridea.com
38
19
  executables:
39
- - youtube_utils
20
+ - youtube_utils
40
21
  extensions: []
41
22
 
42
23
  extra_rdoc_files: []
43
24
 
44
25
  files:
45
- - lib/youtube_utils.rb
46
- - bin/youtube_utils
47
- has_rdoc: true
26
+ - lib/youtube_utils.rb
27
+ - bin/youtube_utils
48
28
  homepage: http://github.com/yong/youtube_utils
49
29
  licenses: []
50
30
 
@@ -52,29 +32,23 @@ post_install_message:
52
32
  rdoc_options: []
53
33
 
54
34
  require_paths:
55
- - lib
35
+ - lib
56
36
  required_ruby_version: !ruby/object:Gem::Requirement
57
37
  none: false
58
38
  requirements:
59
- - - ">="
60
- - !ruby/object:Gem::Version
61
- hash: 3
62
- segments:
63
- - 0
64
- version: "0"
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ version: "0"
65
42
  required_rubygems_version: !ruby/object:Gem::Requirement
66
43
  none: false
67
44
  requirements:
68
- - - ">="
69
- - !ruby/object:Gem::Version
70
- hash: 3
71
- segments:
72
- - 0
73
- version: "0"
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: "0"
74
48
  requirements: []
75
49
 
76
50
  rubyforge_project:
77
- rubygems_version: 1.3.7
51
+ rubygems_version: 1.8.9
78
52
  signing_key:
79
53
  specification_version: 3
80
54
  summary: youtube downloader