svt-recorder 1.0.0 → 1.0.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.
data/ChangeLog CHANGED
@@ -1,3 +1,16 @@
1
+ 2012-09-09 Björn Andersson <ba@sanitarium.se>, v1.0.1
2
+
3
+ User request for a better progress bar, so I've obliged with the
4
+ excellent `progress_bar` gem by Paul Sadauskas.
5
+ https://github.com/paul/progress_bar
6
+
7
+ * svt-recorder uses a new progress bar that estimates time to
8
+ completion, shows how long the download has been going on and
9
+ also displays how many chunks that has been downloaded together
10
+ with the total number of chunks.
11
+ * SVT::Recorder.fetch_playlist doesn't need to be called with
12
+ a block anymore.
13
+
1
14
  2012-06-04 Björn Andersson <ba@sanitarium.se>, v1.0.0
2
15
 
3
16
  SVT has changed their website and thus the way data is fetched.
data/Gemfile CHANGED
@@ -2,8 +2,8 @@ source "http://rubygems.org/"
2
2
 
3
3
  gem 'json_pure', '~> 1.0'
4
4
  gem 'nokogiri', '~> 1.0'
5
+ gem 'progress_bar', '~> 0.4'
5
6
 
6
7
  group :development do
7
8
  gem 'rspec', '~> 2.0'
8
9
  end
9
-
@@ -12,6 +12,7 @@ end
12
12
  require 'tempfile'
13
13
  require 'readline'
14
14
  require 'ostruct'
15
+ require 'progress_bar'
15
16
 
16
17
  if ARGV.empty? or ARGV[0].match(/\A(-h)|((--)?help)\Z/i)
17
18
  puts "Usage: #{$0.split(/\//)[-1]} <SVT Play URL> [name of output file]"
@@ -31,7 +32,6 @@ class HTTPDownload
31
32
  @downloader = downloader
32
33
  @headers = {'User-Agent' => 'Mozilla/5.0 (Windows; U; Windows NT 5.2; en-US; rv:1.9.2.10) Gecko/20100914 Firefox/3.6.10'}
33
34
  @file = output
34
-
35
35
  @server = Net::HTTP.start(@base_url.host, @base_url.port)
36
36
 
37
37
  if block_given?
@@ -53,15 +53,8 @@ class HTTPDownload
53
53
  begin
54
54
  @server.request_get(File.join(@base_url.path, part),
55
55
  @headers) do |res|
56
-
57
56
  res.read_body do |body|
58
57
  file.write body
59
- downloaded += body.size
60
-
61
- if downloaded >= megabyte
62
- downloaded -= megabyte
63
- yield mb_down += 1
64
- end
65
58
  end
66
59
  end # /@server
67
60
  rescue Timeout::Error
@@ -69,7 +62,9 @@ class HTTPDownload
69
62
  @server = Net::HTTP.start(@base_url.host, @base_url.port)
70
63
  retry
71
64
  end
72
- end # /@list
65
+
66
+ yield part
67
+ end # /parts
73
68
  end # /File
74
69
  end
75
70
 
@@ -102,8 +97,8 @@ if File.exists? output_file
102
97
  exit 1 unless overwrite.match(/Y/i)
103
98
  end
104
99
 
100
+ progress = ProgressBar.new(downloader.parts?, :bar, :elapsed, :eta, :counter)
105
101
  HTTPDownload.new(downloader, output_file) do |down|
106
- print "Progress: "
107
- down.fetch_all {|part| print (part > 0)? '.': 'r' }
102
+ down.fetch_all {|part| progress.increment! }
108
103
  puts "\nFinished recording: #{output_file}"
109
104
  end
@@ -33,6 +33,6 @@ module SVT #:nodoc:
33
33
  end
34
34
  end
35
35
 
36
- VERSION = '1.0.0'
36
+ VERSION = '1.0.1'
37
37
  end
38
38
  end
@@ -1,5 +1,6 @@
1
1
  #!/usr/bin/env ruby
2
2
  # -*- coding: utf-8 -*-
3
+ require 'cgi'
3
4
 
4
5
  module SVT
5
6
  module Recorder
@@ -16,6 +17,7 @@ module SVT
16
17
  # url :: The URL from data-json-href, Play have to add modify the URL
17
18
  # to make it absolute. So the caller makes any modifications
18
19
  # before the JSON-file gets fetched.
20
+ # Not required to work.
19
21
  #
20
22
  # Returns:
21
23
  # A hash with these keys:
@@ -24,18 +26,18 @@ module SVT
24
26
  def self.fetch_playlist(url, css_path)
25
27
  doc = Nokogiri::HTML(open(url).read)
26
28
  player = doc.at_css(css_path)
27
- stream = player['data-json-href']
28
- stream = yield stream
29
+ stream = CGI.unescape(player['data-json-href'])
30
+ stream = yield stream if block_given?
29
31
 
30
32
  js = JSON.parse(open(stream).read)
31
33
  if not js['video']['availableOnMobile']
32
- raise ArgumentError, "The passed in URL is not available for mobile, non-rtmp"
34
+ raise ArgumentError, "The passed in URL is not available for mobile"
33
35
  end
34
36
 
35
37
  title = js['context']['title']
36
38
  v = js['video']['videoReferences'].find({}) {|v| v['playerType'] == 'ios' }
37
39
 
38
- {:title => title, :url => v['url']}
40
+ return({:title => title, :url => CGI.unescape(v['url'])}) if not v.empty?
39
41
  end
40
42
 
41
43
  class Base
@@ -115,6 +117,16 @@ module SVT
115
117
  end
116
118
  end
117
119
 
120
+ # Returns the number of parts this recording got
121
+ #
122
+ # Returns:
123
+ # int the numbers of parts, 0 index
124
+ def parts?
125
+ part_urls() if @last_part == 0
126
+
127
+ return @last_part
128
+ end
129
+
118
130
  # Yields all +parts+ concatenated with base_url
119
131
  def all_parts
120
132
  parts do |part|
@@ -124,6 +136,7 @@ module SVT
124
136
 
125
137
  #--
126
138
  # A naïve parser, but until it turns out to be a problem it'll do.
139
+ # 2012=09-09: If a FQDN address is given only return the basename
127
140
  #
128
141
  # The format is:
129
142
  # EXT-X-.... BANDWIDTH=<bitrate>
@@ -132,9 +145,10 @@ module SVT
132
145
  bitrate = nil
133
146
  open(@stream).each do |row|
134
147
  row.strip!
148
+ row = File.basename(row) if row.match(/^http/)
135
149
 
136
150
  if bitrate
137
- @bitrates[bitrate] = row
151
+ @bitrates[bitrate] = CGI.escape(row)
138
152
  bitrate = nil
139
153
  end
140
154
 
@@ -15,7 +15,7 @@ module SVT
15
15
  # Usage is the same as for SVT::Recorder::Play.
16
16
  class Rapport < Base
17
17
  def initialize(url)
18
- video = SVT::Recorder.fetch_playlist(url, '.svtplayer') {|url| url }
18
+ video = SVT::Recorder.fetch_playlist(url, '.svtplayer')
19
19
 
20
20
  super(video)
21
21
  end
@@ -3,3 +3,4 @@ require 'svt/recorder'
3
3
  $play_html = 'spec/support/example-page.html'
4
4
  $faulty_play_html = 'spec/support/faulty-example-page.html'
5
5
  $rapport_url = 'spec/support/rapport.html'
6
+ $stream_http = 'spec/support/streams-with-http.m3u8'
@@ -415,7 +415,7 @@ data-title="&#034;Jag var jättestressad i finalen&#034; - SVT.se"
415
415
  data-length="535"
416
416
  data-id="113083"
417
417
  data-popout-href="http://svt.se/wd?widgetId=32050&amp;sectionId=532&amp;articleId=113083&amp;type=embed&amp;contextSectionId=532"
418
- data-json-href="http://svt.se/wd?widgetId=32050&amp;sectionId=532&amp;articleId=113083&amp;position=0&amp;format=json&amp;type=embed&amp;contextSectionId=532"
418
+ data-json-href="spec/support/rapport.json"
419
419
  data-embed-href="http://svt.se/wd?widgetId=32050&amp;sectionId=532&amp;articleId=113083&amp;type=embed&amp;contextSectionId=532"
420
420
  data-disabled="end">
421
421
  <img class="svtJsReplaceImage svtPlayerImage" alt=" " src="/svts/article113082.svt/ALTERNATES/large/default_title" />
@@ -772,4 +772,4 @@ $(document).ready(function() {
772
772
  <img src="http://ld.svt.se/svt/svt/s?svtse.nyheter.nyhetsklipp.nyheter.%22jag-var-j%C3%A4ttestressad-i-finalen%22&amp;svt_section_id=532&amp;svt_program_name=nyheter&amp;svt_section_name=nyheter&amp;svt_article_title=%22jag-var-j%C3%A4ttestressad-i-finalen%22&amp;svt_context_id=532&amp;svt_context_name=nyheter&amp;svt_cat_name=nyheter&amp;svt_article_type=videoklipp&amp;svt_article_id=113083&amp;client=web" width="1" height="1" alt=""/>
773
773
  </noscript>
774
774
  <script type="text/javascript">if (!NREUMQ.f) { NREUMQ.f=function() {NREUMQ.push(["load",new Date().getTime()]);var e=document.createElement("script");e.type="text/javascript";e.src=(("http:"===document.location.protocol)?"http:":"https:") + "//" + "d1ros97qkrwjf5.cloudfront.net/34/eum/rum.js";document.body.appendChild(e);if(NREUMQ.a)NREUMQ.a();};NREUMQ.a=window.onload;window.onload=NREUMQ.f;};NREUMQ.push(["nrfj","beacon-1.newrelic.com","7aa7765553",908109,"bwdWYRFVV0AEU0BfDlZNfmYzG01WCEBYVxVdTVdaDllWXUtaR0Y=",0,297,new Date().getTime(),"","","","",""]);</script></body>
775
- </html>
775
+ </html>
@@ -0,0 +1,13 @@
1
+ #EXTM3U
2
+ #EXT-X-STREAM-INF:PROGRAM-ID=1, BANDWIDTH=258450
3
+ http://whatever.ding.se/hej/PG-1279307-001A-DOKUMENTUTIFRAN-02-hts-a-v1_Layer1_vod.m3u8
4
+ #EXT-X-STREAM-INF:PROGRAM-ID=1, BANDWIDTH=697107
5
+ http://whatever.ding.se/hej/PG-1279307-001A-DOKUMENTUTIFRAN-02-hts-a-v1_Layer2_vod.m3u8
6
+ #EXT-X-STREAM-INF:PROGRAM-ID=1, BANDWIDTH=143234
7
+ http://whatever.ding.se/hej/PG-1279307-001A-DOKUMENTUTIFRAN-02-hts-a-v1_Layer3_vod.m3u8
8
+ #EXT-X-STREAM-INF:PROGRAM-ID=1, BANDWIDTH=49212
9
+ http://whatever.ding.se/hej/PG-1279307-001A-DOKUMENTUTIFRAN-02-hts-a-v1_Layer4_vod.m3u8
10
+ #EXT-X-STREAM-INF:PROGRAM-ID=1, BANDWIDTH=1364631
11
+ http://whatever.ding.se/hej/PG-1279307-001A-DOKUMENTUTIFRAN-02-hts-a-v1_Layer5_vod.m3u8
12
+ #EXT-X-STREAM-INF:PROGRAM-ID=1, BANDWIDTH=2498313, CODECS="avc1.4d001f"
13
+ http://whatever.ding.se/hej/PG-1279307-001A-DOKUMENTUTIFRAN-02-hts-a-v1_Layer6_vod.m3u8
@@ -21,6 +21,14 @@ module SVT
21
21
 
22
22
  data.title.should == title
23
23
  end
24
+
25
+ it 'should handle streams with http and just give of the basename' do
26
+ # An error when fetching Rapport videos, the playlist at times had
27
+ # a FQDN
28
+ data = SVT::Recorder::Base.new({:url => $stream_http,
29
+ :title => 'Whatever'})
30
+ data.parts[0].should == 'PG-1279307-001A-DOKUMENTUTIFRAN-02-hts-a-v1_Layer6/3512_Period1/segment0.ts'
31
+ end
24
32
  end
25
33
 
26
34
  let(:title) { 'Glödlampskonspirationen' }
@@ -87,7 +95,12 @@ module SVT
87
95
  recorder.parts[0].should == 'PG-1279307-001A-DOKUMENTUTIFRAN-02-hts-a-v1_Layer6/3512_Period1/segment0.ts'
88
96
  end
89
97
  end
98
+
99
+ describe '#parts?' do
100
+ it 'should return the amount of parts in this recording' do
101
+ recorder.parts?().should == no_parts
102
+ end
103
+ end
90
104
  end # /Play
91
105
  end # /Recorder
92
106
  end # /SVT
93
-
@@ -20,6 +20,6 @@ Gem::Specification.new do |s|
20
20
  s.rdoc_options << '-x spec --main lib/svt/recorder.rb --line-numbers'
21
21
  s.add_dependency('json_pure', '~> 1.0')
22
22
  s.add_dependency('nokogiri', '~> 1.0')
23
+ s.add_dependency('progress_bar', '~> 0.4')
23
24
  s.add_development_dependency('rspec', '~> 2.0.0')
24
25
  end
25
-
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: svt-recorder
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.0.1
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-06-04 00:00:00.000000000 Z
12
+ date: 2012-09-08 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: json_pure
16
- requirement: &75889310 !ruby/object:Gem::Requirement
16
+ requirement: !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ~>
@@ -21,21 +21,47 @@ dependencies:
21
21
  version: '1.0'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *75889310
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: '1.0'
25
30
  - !ruby/object:Gem::Dependency
26
31
  name: nokogiri
27
- requirement: &76400980 !ruby/object:Gem::Requirement
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ~>
36
+ - !ruby/object:Gem::Version
37
+ version: '1.0'
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
28
41
  none: false
29
42
  requirements:
30
43
  - - ~>
31
44
  - !ruby/object:Gem::Version
32
45
  version: '1.0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: progress_bar
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ~>
52
+ - !ruby/object:Gem::Version
53
+ version: '0.4'
33
54
  type: :runtime
34
55
  prerelease: false
35
- version_requirements: *76400980
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: '0.4'
36
62
  - !ruby/object:Gem::Dependency
37
63
  name: rspec
38
- requirement: &76413220 !ruby/object:Gem::Requirement
64
+ requirement: !ruby/object:Gem::Requirement
39
65
  none: false
40
66
  requirements:
41
67
  - - ~>
@@ -43,7 +69,12 @@ dependencies:
43
69
  version: 2.0.0
44
70
  type: :development
45
71
  prerelease: false
46
- version_requirements: *76413220
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ~>
76
+ - !ruby/object:Gem::Version
77
+ version: 2.0.0
47
78
  description: A program that helps you record videos from SVTPlay.se and PlayRapport.se
48
79
  email: ba@sanitarium.se
49
80
  executables:
@@ -58,21 +89,22 @@ files:
58
89
  - Gemfile
59
90
  - svt-recorder.gemspec
60
91
  - ChangeLog
61
- - lib/svt/recorder.rb
62
92
  - lib/svt/recorder/base.rb
63
- - lib/svt/recorder/rapport.rb
64
93
  - lib/svt/recorder/play.rb
65
- - spec/svt_recorder_rapport_spec.rb
94
+ - lib/svt/recorder/rapport.rb
95
+ - lib/svt/recorder.rb
66
96
  - spec/spec_helper.rb
67
97
  - spec/svt_recorder_play_spec.rb
98
+ - spec/svt_recorder_rapport_spec.rb
68
99
  - spec/svt_recorder_spec.rb
69
- - spec/support/109244-nomobile
70
100
  - spec/support/109244
101
+ - spec/support/109244-nomobile
71
102
  - spec/support/example-page.html
72
- - spec/support/rapport.json
103
+ - spec/support/faulty-example-page.html
73
104
  - spec/support/PG-1279307-001A-DOKUMENTUTIFRAN-02-hts-a-v1_Layer6_vod.m3u8
74
105
  - spec/support/rapport.html
75
- - spec/support/faulty-example-page.html
106
+ - spec/support/rapport.json
107
+ - spec/support/streams-with-http.m3u8
76
108
  - spec/support/streams.m3u8
77
109
  - bin/svt-recorder
78
110
  homepage: http://github.com/gaqzi/svt-recorder
@@ -96,11 +128,11 @@ required_rubygems_version: !ruby/object:Gem::Requirement
96
128
  version: '0'
97
129
  requirements: []
98
130
  rubyforge_project:
99
- rubygems_version: 1.8.15
131
+ rubygems_version: 1.8.24
100
132
  signing_key:
101
133
  specification_version: 3
102
134
  summary: A program that helps you record videos from SVTPlay.se and PlayRapport.se
103
135
  test_files:
104
- - spec/svt_recorder_rapport_spec.rb
105
136
  - spec/svt_recorder_play_spec.rb
137
+ - spec/svt_recorder_rapport_spec.rb
106
138
  - spec/svt_recorder_spec.rb