rbtune 1.0.2 → 1.0.3
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.
- checksums.yaml +4 -4
- data/lib/player/ffmpeg.rb +4 -3
- data/lib/rbtune/agqr.rb +2 -23
- data/lib/rbtune/jcba.rb +0 -1
- data/lib/rbtune/listenradio.rb +0 -8
- data/lib/rbtune/radiko.rb +25 -75
- data/lib/rbtune/radio.rb +7 -2
- data/lib/rbtune/radiru.rb +29 -39
- data/lib/rbtune/simul.rb +1 -7
- data/lib/rbtune/timefree.rb +0 -11
- data/lib/rbtune/version.rb +1 -1
- data/rbtune.gemspec +1 -4
- metadata +6 -34
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e1f2f619e38457d2d012382678f54a2af34d07eae09af7502b4b43a68e11d07a
|
4
|
+
data.tar.gz: ba87857b776104f945d459a08cf8e197768dba41530ede82b9fc1193d501c517
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1218ee9599058b710516372428646e10b86c7a411255b32140090149a036f5afb5691a91d0d57b34964dc2a3e58f5da147527d8aa373bf24815cf8488333a25c
|
7
|
+
data.tar.gz: fb3320bf9e149348f6bb45f870eba5bc17f5209758cddff2dc87181df6419b9f0fd7350a419485358fc987c069f32dc1b2d52cb3f602d1861cb8704db34803bd
|
data/lib/player/ffmpeg.rb
CHANGED
@@ -4,7 +4,8 @@ require "open3"
|
|
4
4
|
require "player/mplayer"
|
5
5
|
|
6
6
|
class FFMpeg < Player
|
7
|
-
def initialize
|
7
|
+
def initialize(hash={})
|
8
|
+
self.merge! hash
|
8
9
|
self['loglevel'] = 'warning'
|
9
10
|
self['n'] = '' # do not overwrite
|
10
11
|
@mplayer = Mplayer.new('-')
|
@@ -28,7 +29,7 @@ class FFMpeg < Player
|
|
28
29
|
|
29
30
|
def play
|
30
31
|
self['f'] = 'mpegts'
|
31
|
-
@output = '
|
32
|
+
@output = '-'
|
32
33
|
cmd = "#{to_s} | #{@mplayer}"
|
33
34
|
$stderr.puts 'play: '+cmd
|
34
35
|
`#{cmd}`
|
@@ -43,7 +44,7 @@ class FFMpeg < Player
|
|
43
44
|
cmd = to_s
|
44
45
|
else
|
45
46
|
self['f'] = 'mpegts'
|
46
|
-
@output = '
|
47
|
+
@output = '-'
|
47
48
|
cmd = "#{to_s} | tee #{file} | #{@mplayer}"
|
48
49
|
end
|
49
50
|
|
data/lib/rbtune/agqr.rb
CHANGED
@@ -1,36 +1,15 @@
|
|
1
1
|
# 文化放送 超A&G+ を受信する
|
2
2
|
|
3
3
|
require "rbtune/radio"
|
4
|
-
require "player/rtmpdump"
|
5
|
-
require "player/ffmpeg"
|
6
|
-
require "fileutils"
|
7
4
|
|
8
5
|
class Agqr < Radio
|
9
6
|
def initialize
|
10
|
-
@ext
|
11
|
-
@out_ext = 'm4a'
|
7
|
+
@ext = 'm4a'
|
12
8
|
end
|
13
9
|
|
14
10
|
def fetch_stations
|
15
|
-
uri =
|
11
|
+
uri = 'https://fms2.uniqueradio.jp/agqr10/aandg1.m3u8'
|
16
12
|
[Station.new('AGQR', uri, name: '超A&G+', ascii_name: 'aandg1')]
|
17
13
|
end
|
18
14
|
|
19
|
-
|
20
|
-
def create_player(uri)
|
21
|
-
rtmpdump = RtmpDump.new
|
22
|
-
rtmpdump['rtmp'] = uri
|
23
|
-
rtmpdump
|
24
|
-
end
|
25
|
-
|
26
|
-
|
27
|
-
def convert(tmpfile, recfile)
|
28
|
-
ffmpeg = FFMpeg.new
|
29
|
-
ffmpeg['loglevel'] = 'quiet'
|
30
|
-
ffmpeg['i'] = %Q("#{tmpfile}")
|
31
|
-
ffmpeg['acodec'] = 'copy'
|
32
|
-
stdout, stderr, status = ffmpeg.rec recfile, nil
|
33
|
-
FileUtils.rm tmpfile if status.success?
|
34
|
-
end
|
35
|
-
|
36
15
|
end
|
data/lib/rbtune/jcba.rb
CHANGED
data/lib/rbtune/listenradio.rb
CHANGED
@@ -5,7 +5,6 @@
|
|
5
5
|
|
6
6
|
|
7
7
|
require "rbtune/radio"
|
8
|
-
require "player/ffmpeg"
|
9
8
|
require "json"
|
10
9
|
|
11
10
|
|
@@ -16,13 +15,6 @@ class ListenRadio < Radio
|
|
16
15
|
@ext = 'mp4'
|
17
16
|
end
|
18
17
|
|
19
|
-
def create_player(uri)
|
20
|
-
player = FFMpeg.new
|
21
|
-
player['i'] = uri # input stream
|
22
|
-
player['acodec'] = 'copy' # acodecオプションはiオプションのあとに置かないとエラー
|
23
|
-
player
|
24
|
-
end
|
25
|
-
|
26
18
|
|
27
19
|
def stations_uri
|
28
20
|
'http://listenradio.jp/service/channel.aspx'
|
data/lib/rbtune/radiko.rb
CHANGED
@@ -3,82 +3,55 @@
|
|
3
3
|
|
4
4
|
require "mechanize"
|
5
5
|
require "rbtune/radio"
|
6
|
-
require "player/rtmpdump"
|
7
|
-
require 'swf_ruby'
|
8
6
|
|
9
7
|
|
10
8
|
class Radiko < Radio
|
11
9
|
attr_reader :authtoken
|
12
10
|
|
13
11
|
|
14
|
-
def playerurl
|
15
|
-
"http://radiko.jp/apps/js/flash/myplayer-release.swf"
|
16
|
-
end
|
17
|
-
|
18
|
-
|
19
|
-
def playerfile
|
20
|
-
"player.swf"
|
21
|
-
end
|
22
|
-
|
23
|
-
|
24
|
-
def keyfile
|
25
|
-
"authkey.png"
|
26
|
-
end
|
27
|
-
|
28
|
-
|
29
12
|
# get_auth2 の返り値により @area_id, @area_ja, @area_en が設定される
|
30
13
|
def open
|
31
|
-
|
32
|
-
|
33
|
-
fetch_file playerurl, playerfile
|
34
|
-
end
|
35
|
-
unless File.exists? keyfile
|
36
|
-
swfextract playerfile, 12, keyfile
|
37
|
-
end
|
38
|
-
|
39
|
-
@authtoken, partialkey = authenticate1 'https://radiko.jp/v2/api/auth1_fms'
|
40
|
-
@area_id, @area_ja, @area_en = authenticate2 'https://radiko.jp/v2/api/auth2_fms', authtoken, partialkey
|
14
|
+
@authtoken, partialkey = authenticate1 'https://radiko.jp/v2/api/auth1'
|
15
|
+
@area_id, @area_ja, @area_en = authenticate2 'https://radiko.jp/v2/api/auth2', authtoken, partialkey
|
41
16
|
puts "area: #{area_id} (#{area_ja}: #{area_en})"
|
42
17
|
end
|
43
18
|
|
44
19
|
|
45
20
|
def channel_to_uri
|
46
|
-
|
47
|
-
xml.
|
21
|
+
uri = "http://radiko.jp/v2/station/stream_smh_multi/#{@channel}.xml"
|
22
|
+
xml = agent.get uri
|
23
|
+
xml.at('//url/playlist_create_url').text
|
48
24
|
end
|
49
25
|
|
50
26
|
|
51
27
|
def create_player(uri)
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
28
|
+
FFMpeg.new( {
|
29
|
+
headers: %Q("X-Radiko-Authtoken: #{authtoken}"),
|
30
|
+
i: %Q("#{uri}"),
|
31
|
+
# acodec: 'copy', # acodecオプションはiオプションのあとに置かないとエラー
|
32
|
+
} )
|
57
33
|
end
|
58
34
|
|
59
35
|
|
60
36
|
def authenticate1(url)
|
61
|
-
|
62
|
-
'
|
63
|
-
'X-Radiko-App'
|
64
|
-
'X-Radiko-App-Version' => '4.0.0',
|
65
|
-
'X-Radiko-User' => 'test-stream',
|
37
|
+
agent.request_headers = {
|
38
|
+
'X-Radiko-App' => 'pc_html5',
|
39
|
+
'X-Radiko-App-Version' => '0.0.1',
|
66
40
|
'X-Radiko-Device' => 'pc',
|
41
|
+
'X-Radiko-User' => 'dummy_user',
|
67
42
|
}
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
length = auth1['X-Radiko-KeyLength'].to_i
|
75
|
-
partialkey = read_partialkey keyfile, offset, length
|
43
|
+
res = agent.get url
|
44
|
+
auth1 = res.response
|
45
|
+
authtoken = auth1['x-radiko-authtoken']
|
46
|
+
offset = auth1['x-radiko-keyoffset'].to_i
|
47
|
+
length = auth1['x-radiko-keylength'].to_i
|
48
|
+
partialkey = read_partialkey offset, length
|
76
49
|
[authtoken, partialkey]
|
77
50
|
end
|
78
51
|
|
79
52
|
|
80
|
-
def read_partialkey(
|
81
|
-
key =
|
53
|
+
def read_partialkey(offset, length)
|
54
|
+
key = "bcd151073c03b352e1ef2fd66c32209da9ca0afa"
|
82
55
|
Base64.encode64(key[offset,length]).chomp
|
83
56
|
end
|
84
57
|
|
@@ -87,15 +60,13 @@ class Radiko < Radio
|
|
87
60
|
def authenticate2(url, authtoken, partialkey)
|
88
61
|
# pp [url, authtoken, partialkey]
|
89
62
|
agent.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
90
|
-
|
91
|
-
'pragma' => 'no-cache',
|
92
|
-
'X-Radiko-App' => 'pc_ts',
|
93
|
-
'X-Radiko-App-Version' => '4.0.0',
|
94
|
-
'X-Radiko-User' => 'test-stream',
|
63
|
+
agent.request_headers = {
|
95
64
|
'X-Radiko-Device' => 'pc',
|
65
|
+
'X-Radiko-User' => 'dummy_user',
|
96
66
|
'X-Radiko-Authtoken' => authtoken,
|
97
67
|
'X-Radiko-Partialkey' => partialkey,
|
98
68
|
}
|
69
|
+
res = agent.get url
|
99
70
|
body = res.body
|
100
71
|
body.force_encoding 'utf-8'
|
101
72
|
body.split(',').map(&:strip)
|
@@ -119,25 +90,4 @@ class Radiko < Radio
|
|
119
90
|
end
|
120
91
|
|
121
92
|
|
122
|
-
def fetch_file(url, file=nil)
|
123
|
-
content = agent.get_file(url)
|
124
|
-
File.open(file, "wb") { |fout| fout.write content } if file
|
125
|
-
content
|
126
|
-
end
|
127
|
-
|
128
|
-
|
129
|
-
def swfextract(swffile, character_id, out_file)
|
130
|
-
swf = SwfRuby::SwfDumper.new
|
131
|
-
swf.open(swffile)
|
132
|
-
swf.tags.each_with_index do |tag, i|
|
133
|
-
tag = swf.tags[i]
|
134
|
-
if tag.character_id && tag.character_id == character_id
|
135
|
-
offset = swf.tags_addresses[i]
|
136
|
-
len = tag.length
|
137
|
-
File.open(out_file, 'wb') { |out| out.print tag.data[6..-1] }
|
138
|
-
break
|
139
|
-
end
|
140
|
-
end
|
141
|
-
end
|
142
|
-
|
143
93
|
end
|
data/lib/rbtune/radio.rb
CHANGED
@@ -10,7 +10,8 @@
|
|
10
10
|
require "date"
|
11
11
|
require "benchmark"
|
12
12
|
require "net/http"
|
13
|
-
require "
|
13
|
+
require "player/ffmpeg"
|
14
|
+
require "rbtune/station"
|
14
15
|
|
15
16
|
class Radio
|
16
17
|
attr_accessor :outdir
|
@@ -89,6 +90,10 @@ class Radio
|
|
89
90
|
|
90
91
|
def create_player(uri)
|
91
92
|
# rtmpdumpのコマンドラインを生成する(playから呼ばれる)
|
93
|
+
FFMpeg.new( {
|
94
|
+
i: uri,
|
95
|
+
# acodec: 'copy', # acodecオプションはiオプションのあとに置かないとエラー
|
96
|
+
} )
|
92
97
|
end
|
93
98
|
|
94
99
|
|
@@ -167,7 +172,7 @@ class Radio
|
|
167
172
|
ffmpeg = FFMpeg.new
|
168
173
|
ffmpeg['loglevel'] = 'quiet'
|
169
174
|
ffmpeg['i'] = %Q("#{tmpfile}")
|
170
|
-
ffmpeg['b:a'] = '70k'
|
175
|
+
# ffmpeg['b:a'] = '70k'
|
171
176
|
stdout, stderr, status = ffmpeg.rec recfile, nil
|
172
177
|
FileUtils.rm tmpfile if status.success?
|
173
178
|
end
|
data/lib/rbtune/radiru.rb
CHANGED
@@ -2,51 +2,41 @@
|
|
2
2
|
# coding: utf-8
|
3
3
|
|
4
4
|
require "rbtune/radio"
|
5
|
-
require "player/ffmpeg"
|
6
|
-
require "fileutils"
|
7
5
|
|
8
6
|
class Radiru < Radio
|
9
7
|
|
10
8
|
|
11
|
-
def
|
12
|
-
|
13
|
-
ffmpeg['i'] = uri # input stream
|
14
|
-
ffmpeg['acodec'] = 'copy' # acodecオプションはiオプションのあとに置かないとエラー
|
15
|
-
ffmpeg
|
9
|
+
def stations_uri
|
10
|
+
"https://www.nhk.or.jp/radio/config/config_web.xml"
|
16
11
|
end
|
17
12
|
|
18
13
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
id = station.id.sub(/-TOKYO/, '')
|
47
|
-
stations.unshift Station.new(id, station.uri, name: station.name, ascii_name: id)
|
48
|
-
end
|
49
|
-
stations
|
50
|
-
end
|
14
|
+
def parse_stations(body)
|
15
|
+
stations = body.search '//data'
|
16
|
+
stationsjp = {
|
17
|
+
'r1' => "ラジオ第1",
|
18
|
+
'r2' => "ラジオ第2",
|
19
|
+
'fm' => "FM",
|
20
|
+
}
|
21
|
+
stations = stations.map do |station|
|
22
|
+
areajp = station.at('areajp').text
|
23
|
+
area = station.at('area').text
|
24
|
+
# 地区ごとに第1, 第2, FM を登録する
|
25
|
+
r1, r2, fm = %w(r1 r2 fm).map do |v|
|
26
|
+
hls = "#{v}hls"
|
27
|
+
id = "nhk#{v}-#{area}".upcase
|
28
|
+
uri = station.at(hls).text
|
29
|
+
name = "NHK#{stationsjp[v]}-#{areajp}"
|
30
|
+
Station.new(id, uri, name: name, ascii_name: id)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
stations.flatten!
|
34
|
+
# id: NHKR1, NHKR2, NHKFM を東京局に割り当てる
|
35
|
+
stations.find_all { |station| station.id =~ /-TOKYO/}.reverse.map do |station|
|
36
|
+
id = station.id.sub(/-TOKYO/, '')
|
37
|
+
stations.unshift Station.new(id, station.uri, name: station.name, ascii_name: id)
|
38
|
+
end
|
39
|
+
stations
|
40
|
+
end
|
51
41
|
|
52
42
|
end
|
data/lib/rbtune/simul.rb
CHANGED
@@ -2,14 +2,13 @@
|
|
2
2
|
|
3
3
|
require "rbtune/radio"
|
4
4
|
require "player/mplayer"
|
5
|
-
require "
|
5
|
+
require "rexml/document"
|
6
6
|
|
7
7
|
class Simul < Radio
|
8
8
|
|
9
9
|
def initialize
|
10
10
|
super
|
11
11
|
@ext = 'asf'
|
12
|
-
@out_ext = 'm4a'
|
13
12
|
end
|
14
13
|
|
15
14
|
|
@@ -44,11 +43,6 @@ class Simul < Radio
|
|
44
43
|
end
|
45
44
|
|
46
45
|
|
47
|
-
def convert(tmpfile, recfile)
|
48
|
-
convert_ffmpeg(tmpfile, recfile)
|
49
|
-
end
|
50
|
-
|
51
|
-
|
52
46
|
def link_to_station_id(link)
|
53
47
|
link =~ %r{(/asx/([\w-]+).asx|nkansai.tv/(\w+)/?\Z|(flower|redswave|fm-tanba|darazfm|AmamiFM|comiten|fm-shimabara|fm-kitaq))}
|
54
48
|
id = ($2 || $3 || $4).sub(/fm[-_]/, 'fm').sub(/[-_]fm/, 'fm')
|
data/lib/rbtune/timefree.rb
CHANGED
@@ -1,8 +1,5 @@
|
|
1
1
|
require "rbtune/radiko_premium"
|
2
|
-
require "rbtune/station"
|
3
|
-
require "player/ffmpeg"
|
4
2
|
require "date"
|
5
|
-
require "fileutils"
|
6
3
|
|
7
4
|
class DateTime
|
8
5
|
def timefree
|
@@ -40,12 +37,4 @@ class TimeFree < RadikoPremium
|
|
40
37
|
end
|
41
38
|
|
42
39
|
|
43
|
-
def create_player(uri)
|
44
|
-
ffmpeg = FFMpeg.new
|
45
|
-
ffmpeg['loglevel'] = 'info'
|
46
|
-
ffmpeg['headers'] = %Q("X-Radiko-AuthToken: #{authtoken}")
|
47
|
-
ffmpeg['i'] = %Q("#{uri}")
|
48
|
-
ffmpeg['acodec'] = 'copy' # acodecオプションはiオプションのあとに置かないとエラー
|
49
|
-
ffmpeg
|
50
|
-
end
|
51
40
|
end
|
data/lib/rbtune/version.rb
CHANGED
data/rbtune.gemspec
CHANGED
@@ -24,11 +24,8 @@ Gem::Specification.new do |spec|
|
|
24
24
|
spec.require_paths = ["lib"]
|
25
25
|
|
26
26
|
spec.add_dependency "mechanize", "~> 2.7"
|
27
|
-
spec.add_dependency "rmagick", "= 2.13.2" # swf_ruby が依存するので固定
|
28
|
-
spec.add_dependency "swf_ruby", "~> 0.2"
|
29
27
|
spec.add_dependency "pit", "~> 0.0.7"
|
30
28
|
spec.add_development_dependency "bundler", "~> 2.1"
|
31
|
-
spec.add_development_dependency "rake", "
|
32
|
-
# spec.add_development_dependency "pry"
|
29
|
+
spec.add_development_dependency "rake", ">= 12.3.3"
|
33
30
|
|
34
31
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rbtune
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- ASAHI,Michiharu
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-07
|
11
|
+
date: 2020-12-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: mechanize
|
@@ -24,34 +24,6 @@ dependencies:
|
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '2.7'
|
27
|
-
- !ruby/object:Gem::Dependency
|
28
|
-
name: rmagick
|
29
|
-
requirement: !ruby/object:Gem::Requirement
|
30
|
-
requirements:
|
31
|
-
- - '='
|
32
|
-
- !ruby/object:Gem::Version
|
33
|
-
version: 2.13.2
|
34
|
-
type: :runtime
|
35
|
-
prerelease: false
|
36
|
-
version_requirements: !ruby/object:Gem::Requirement
|
37
|
-
requirements:
|
38
|
-
- - '='
|
39
|
-
- !ruby/object:Gem::Version
|
40
|
-
version: 2.13.2
|
41
|
-
- !ruby/object:Gem::Dependency
|
42
|
-
name: swf_ruby
|
43
|
-
requirement: !ruby/object:Gem::Requirement
|
44
|
-
requirements:
|
45
|
-
- - "~>"
|
46
|
-
- !ruby/object:Gem::Version
|
47
|
-
version: '0.2'
|
48
|
-
type: :runtime
|
49
|
-
prerelease: false
|
50
|
-
version_requirements: !ruby/object:Gem::Requirement
|
51
|
-
requirements:
|
52
|
-
- - "~>"
|
53
|
-
- !ruby/object:Gem::Version
|
54
|
-
version: '0.2'
|
55
27
|
- !ruby/object:Gem::Dependency
|
56
28
|
name: pit
|
57
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -84,16 +56,16 @@ dependencies:
|
|
84
56
|
name: rake
|
85
57
|
requirement: !ruby/object:Gem::Requirement
|
86
58
|
requirements:
|
87
|
-
- - "
|
59
|
+
- - ">="
|
88
60
|
- !ruby/object:Gem::Version
|
89
|
-
version:
|
61
|
+
version: 12.3.3
|
90
62
|
type: :development
|
91
63
|
prerelease: false
|
92
64
|
version_requirements: !ruby/object:Gem::Requirement
|
93
65
|
requirements:
|
94
|
-
- - "
|
66
|
+
- - ">="
|
95
67
|
- !ruby/object:Gem::Version
|
96
|
-
version:
|
68
|
+
version: 12.3.3
|
97
69
|
description: Playing and Recording Radiko, Radiru*Radiru and the other IP simulcast
|
98
70
|
sites.
|
99
71
|
email:
|