webrtc-ruby 0.1.0
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 +7 -0
- data/.dockerignore +19 -0
- data/.rspec +3 -0
- data/CHANGELOG.md +12 -0
- data/Dockerfile +49 -0
- data/LICENSE +21 -0
- data/README.md +257 -0
- data/Rakefile +42 -0
- data/examples/signaling_server/server.rb +200 -0
- data/examples/simple_data_channel.rb +81 -0
- data/examples/video_call.rb +152 -0
- data/ext/webrtc_ruby/CMakeLists.txt +84 -0
- data/ext/webrtc_ruby/Makefile +31 -0
- data/ext/webrtc_ruby/webrtc_ruby.c +757 -0
- data/ext/webrtc_ruby/webrtc_ruby.h +169 -0
- data/lib/webrtc/configuration.rb +99 -0
- data/lib/webrtc/data_channel.rb +154 -0
- data/lib/webrtc/dtls_transport.rb +54 -0
- data/lib/webrtc/dtmf_sender.rb +81 -0
- data/lib/webrtc/errors.rb +10 -0
- data/lib/webrtc/ffi/library.rb +100 -0
- data/lib/webrtc/ice_candidate.rb +62 -0
- data/lib/webrtc/ice_transport.rb +95 -0
- data/lib/webrtc/media_stream.rb +67 -0
- data/lib/webrtc/media_stream_track.rb +83 -0
- data/lib/webrtc/peer_connection.rb +346 -0
- data/lib/webrtc/promise.rb +59 -0
- data/lib/webrtc/rtp_receiver.rb +51 -0
- data/lib/webrtc/rtp_sender.rb +85 -0
- data/lib/webrtc/rtp_transceiver.rb +34 -0
- data/lib/webrtc/sctp_transport.rb +31 -0
- data/lib/webrtc/session_description.rb +64 -0
- data/lib/webrtc/stats_report.rb +199 -0
- data/lib/webrtc/version.rb +5 -0
- data/lib/webrtc.rb +38 -0
- data/webrtc-ruby.gemspec +33 -0
- metadata +107 -0
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module WebRTC
|
|
4
|
+
class RTCRtpReceiver
|
|
5
|
+
attr_reader :track, :transport
|
|
6
|
+
|
|
7
|
+
def initialize(options = {})
|
|
8
|
+
@track = options[:track]
|
|
9
|
+
@transport = options[:transport]
|
|
10
|
+
@ptr = options[:ptr]
|
|
11
|
+
@parameters = default_parameters
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def self.get_capabilities(kind)
|
|
15
|
+
{
|
|
16
|
+
codecs: default_codecs(kind),
|
|
17
|
+
header_extensions: []
|
|
18
|
+
}
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def self.default_codecs(kind)
|
|
22
|
+
RTCRtpSender.default_codecs(kind)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def get_parameters
|
|
26
|
+
@parameters.dup
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def get_contributing_sources
|
|
30
|
+
[]
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def get_synchronization_sources
|
|
34
|
+
[]
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def get_stats
|
|
38
|
+
Promise.resolve({})
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
private
|
|
42
|
+
|
|
43
|
+
def default_parameters
|
|
44
|
+
{
|
|
45
|
+
header_extensions: [],
|
|
46
|
+
rtcp: { cname: '', reduced_size: false },
|
|
47
|
+
codecs: []
|
|
48
|
+
}
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module WebRTC
|
|
4
|
+
class RTCRtpSender
|
|
5
|
+
attr_reader :track, :transport, :dtmf
|
|
6
|
+
|
|
7
|
+
def initialize(options = {})
|
|
8
|
+
@track = options[:track]
|
|
9
|
+
@transport = options[:transport]
|
|
10
|
+
@ptr = options[:ptr]
|
|
11
|
+
@parameters = default_parameters
|
|
12
|
+
@dtmf = create_dtmf_sender
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
private def create_dtmf_sender
|
|
16
|
+
return nil unless @track&.kind == :audio
|
|
17
|
+
|
|
18
|
+
RTCDTMFSender.new(sender: self)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
public
|
|
22
|
+
|
|
23
|
+
def self.get_capabilities(kind)
|
|
24
|
+
{
|
|
25
|
+
codecs: default_codecs(kind),
|
|
26
|
+
header_extensions: []
|
|
27
|
+
}
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def self.default_codecs(kind)
|
|
31
|
+
case kind.to_sym
|
|
32
|
+
when :audio
|
|
33
|
+
[
|
|
34
|
+
{ mime_type: 'audio/opus', clock_rate: 48_000, channels: 2 },
|
|
35
|
+
{ mime_type: 'audio/PCMU', clock_rate: 8000, channels: 1 },
|
|
36
|
+
{ mime_type: 'audio/PCMA', clock_rate: 8000, channels: 1 }
|
|
37
|
+
]
|
|
38
|
+
when :video
|
|
39
|
+
[
|
|
40
|
+
{ mime_type: 'video/VP8', clock_rate: 90_000 },
|
|
41
|
+
{ mime_type: 'video/VP9', clock_rate: 90_000 },
|
|
42
|
+
{ mime_type: 'video/H264', clock_rate: 90_000 }
|
|
43
|
+
]
|
|
44
|
+
else
|
|
45
|
+
[]
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def get_parameters
|
|
50
|
+
@parameters.dup
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def set_parameters(parameters)
|
|
54
|
+
@parameters = parameters
|
|
55
|
+
Promise.resolve(nil)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def replace_track(new_track)
|
|
59
|
+
Promise.new do
|
|
60
|
+
@track = new_track
|
|
61
|
+
nil
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def set_streams(*streams)
|
|
66
|
+
@streams = streams
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def get_stats
|
|
70
|
+
Promise.resolve({})
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
private
|
|
74
|
+
|
|
75
|
+
def default_parameters
|
|
76
|
+
{
|
|
77
|
+
transaction_id: '',
|
|
78
|
+
encodings: [],
|
|
79
|
+
header_extensions: [],
|
|
80
|
+
rtcp: { cname: '', reduced_size: false },
|
|
81
|
+
codecs: []
|
|
82
|
+
}
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module WebRTC
|
|
4
|
+
class RTCRtpTransceiver
|
|
5
|
+
DIRECTIONS = %i[sendrecv sendonly recvonly inactive stopped].freeze
|
|
6
|
+
|
|
7
|
+
attr_reader :mid, :sender, :receiver, :stopped, :current_direction
|
|
8
|
+
attr_accessor :direction
|
|
9
|
+
|
|
10
|
+
def initialize(options = {})
|
|
11
|
+
@mid = options[:mid]
|
|
12
|
+
@sender = options[:sender] || RTCRtpSender.new
|
|
13
|
+
@receiver = options[:receiver] || RTCRtpReceiver.new
|
|
14
|
+
@direction = options[:direction] || :sendrecv
|
|
15
|
+
@current_direction = nil
|
|
16
|
+
@stopped = false
|
|
17
|
+
@ptr = options[:ptr]
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def stop
|
|
21
|
+
@stopped = true
|
|
22
|
+
@direction = :stopped
|
|
23
|
+
@sender&.replace_track(nil)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def set_codec_preferences(codecs)
|
|
27
|
+
@codec_preferences = codecs
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def stopped?
|
|
31
|
+
@stopped
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module WebRTC
|
|
4
|
+
class RTCSctpTransport
|
|
5
|
+
STATES = %i[connecting connected closed].freeze
|
|
6
|
+
|
|
7
|
+
attr_reader :transport, :max_message_size, :max_channels, :state
|
|
8
|
+
|
|
9
|
+
def initialize(options = {})
|
|
10
|
+
@transport = options[:transport] || RTCDtlsTransport.new
|
|
11
|
+
@state = :connecting
|
|
12
|
+
@max_message_size = options[:max_message_size] || 262_144
|
|
13
|
+
@max_channels = options[:max_channels] || 65_535
|
|
14
|
+
@callbacks = {}
|
|
15
|
+
@ptr = options[:ptr]
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def on_state_change(&block)
|
|
19
|
+
@callbacks[:state_change] = block
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
private
|
|
23
|
+
|
|
24
|
+
def set_state(new_state)
|
|
25
|
+
return if @state == new_state
|
|
26
|
+
|
|
27
|
+
@state = new_state
|
|
28
|
+
@callbacks[:state_change]&.call
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module WebRTC
|
|
4
|
+
class RTCSessionDescription
|
|
5
|
+
TYPES = %i[offer answer pranswer rollback].freeze
|
|
6
|
+
|
|
7
|
+
attr_reader :type, :sdp
|
|
8
|
+
|
|
9
|
+
def initialize(init = {})
|
|
10
|
+
@type = normalize_type(init[:type])
|
|
11
|
+
@sdp = init[:sdp] || ''
|
|
12
|
+
@ptr = nil
|
|
13
|
+
|
|
14
|
+
validate!
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def self.from_ptr(ptr)
|
|
18
|
+
return nil if ptr.nil? || ptr.null?
|
|
19
|
+
|
|
20
|
+
type_str = FFI.webrtc_session_description_get_type(ptr)
|
|
21
|
+
sdp_str = FFI.webrtc_session_description_get_sdp(ptr)
|
|
22
|
+
|
|
23
|
+
desc = new(type: type_str&.to_sym, sdp: sdp_str)
|
|
24
|
+
desc.instance_variable_set(:@ptr, ptr)
|
|
25
|
+
desc
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def to_ptr
|
|
29
|
+
return @ptr if @ptr && !@ptr.null?
|
|
30
|
+
|
|
31
|
+
error = FFI::Error.new
|
|
32
|
+
@ptr = FFI.webrtc_session_description_create(type.to_s, sdp, error)
|
|
33
|
+
raise OperationError, error[:message] if error[:code] != 0
|
|
34
|
+
|
|
35
|
+
@ptr
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def to_h
|
|
39
|
+
{ type: type, sdp: sdp }
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def release
|
|
43
|
+
return unless @ptr && !@ptr.null?
|
|
44
|
+
|
|
45
|
+
FFI.webrtc_session_description_destroy(@ptr)
|
|
46
|
+
@ptr = nil
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
private
|
|
50
|
+
|
|
51
|
+
def normalize_type(type)
|
|
52
|
+
return nil if type.nil?
|
|
53
|
+
|
|
54
|
+
type.to_sym
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def validate!
|
|
58
|
+
return if type.nil?
|
|
59
|
+
return if TYPES.include?(type)
|
|
60
|
+
|
|
61
|
+
raise InvalidParameterError, "Invalid session description type: #{type}"
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module WebRTC
|
|
4
|
+
class RTCStatsReport
|
|
5
|
+
include Enumerable
|
|
6
|
+
|
|
7
|
+
def initialize(stats = {})
|
|
8
|
+
@stats = stats
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def [](id)
|
|
12
|
+
@stats[id]
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def each(&block)
|
|
16
|
+
@stats.each(&block)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def size
|
|
20
|
+
@stats.size
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def keys
|
|
24
|
+
@stats.keys
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def values
|
|
28
|
+
@stats.values
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def get(id)
|
|
32
|
+
@stats[id]
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def has?(id)
|
|
36
|
+
@stats.key?(id)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def to_h
|
|
40
|
+
@stats.dup
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
class RTCStats
|
|
45
|
+
TYPES = %i[
|
|
46
|
+
codec inbound_rtp outbound_rtp remote_inbound_rtp remote_outbound_rtp
|
|
47
|
+
media_source csrc peer_connection data_channel transceiver sender
|
|
48
|
+
receiver transport candidate_pair local_candidate remote_candidate
|
|
49
|
+
certificate ice_server
|
|
50
|
+
].freeze
|
|
51
|
+
|
|
52
|
+
attr_reader :id, :timestamp, :type
|
|
53
|
+
|
|
54
|
+
def initialize(options = {})
|
|
55
|
+
@id = options[:id] || generate_id
|
|
56
|
+
@timestamp = options[:timestamp] || Time.now.to_f * 1000
|
|
57
|
+
@type = options[:type]
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def to_h
|
|
61
|
+
{
|
|
62
|
+
id: @id,
|
|
63
|
+
timestamp: @timestamp,
|
|
64
|
+
type: @type
|
|
65
|
+
}
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
private
|
|
69
|
+
|
|
70
|
+
def generate_id
|
|
71
|
+
"stats-#{SecureRandom.uuid}"
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
class RTCInboundRtpStreamStats < RTCStats
|
|
76
|
+
attr_reader :ssrc, :kind, :packets_received, :bytes_received, :packets_lost, :jitter, :frames_decoded,
|
|
77
|
+
:frames_dropped
|
|
78
|
+
|
|
79
|
+
def initialize(options = {})
|
|
80
|
+
super(options.merge(type: :inbound_rtp))
|
|
81
|
+
@ssrc = options[:ssrc]
|
|
82
|
+
@kind = options[:kind]
|
|
83
|
+
@packets_received = options[:packets_received] || 0
|
|
84
|
+
@bytes_received = options[:bytes_received] || 0
|
|
85
|
+
@packets_lost = options[:packets_lost] || 0
|
|
86
|
+
@jitter = options[:jitter] || 0.0
|
|
87
|
+
@frames_decoded = options[:frames_decoded] || 0
|
|
88
|
+
@frames_dropped = options[:frames_dropped] || 0
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def to_h
|
|
92
|
+
super.merge(
|
|
93
|
+
ssrc: @ssrc,
|
|
94
|
+
kind: @kind,
|
|
95
|
+
packetsReceived: @packets_received,
|
|
96
|
+
bytesReceived: @bytes_received,
|
|
97
|
+
packetsLost: @packets_lost,
|
|
98
|
+
jitter: @jitter,
|
|
99
|
+
framesDecoded: @frames_decoded,
|
|
100
|
+
framesDropped: @frames_dropped
|
|
101
|
+
)
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
class RTCOutboundRtpStreamStats < RTCStats
|
|
106
|
+
attr_reader :ssrc, :kind, :packets_sent, :bytes_sent, :frames_encoded, :target_bitrate, :frames_per_second
|
|
107
|
+
|
|
108
|
+
def initialize(options = {})
|
|
109
|
+
super(options.merge(type: :outbound_rtp))
|
|
110
|
+
@ssrc = options[:ssrc]
|
|
111
|
+
@kind = options[:kind]
|
|
112
|
+
@packets_sent = options[:packets_sent] || 0
|
|
113
|
+
@bytes_sent = options[:bytes_sent] || 0
|
|
114
|
+
@frames_encoded = options[:frames_encoded] || 0
|
|
115
|
+
@target_bitrate = options[:target_bitrate]
|
|
116
|
+
@frames_per_second = options[:frames_per_second]
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
def to_h
|
|
120
|
+
super.merge(
|
|
121
|
+
ssrc: @ssrc,
|
|
122
|
+
kind: @kind,
|
|
123
|
+
packetsSent: @packets_sent,
|
|
124
|
+
bytesSent: @bytes_sent,
|
|
125
|
+
framesEncoded: @frames_encoded,
|
|
126
|
+
targetBitrate: @target_bitrate,
|
|
127
|
+
framesPerSecond: @frames_per_second
|
|
128
|
+
)
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
class RTCTransportStats < RTCStats
|
|
133
|
+
attr_reader :bytes_sent, :bytes_received, :dtls_state, :selected_candidate_pair_id
|
|
134
|
+
|
|
135
|
+
def initialize(options = {})
|
|
136
|
+
super(options.merge(type: :transport))
|
|
137
|
+
@bytes_sent = options[:bytes_sent] || 0
|
|
138
|
+
@bytes_received = options[:bytes_received] || 0
|
|
139
|
+
@dtls_state = options[:dtls_state] || :new
|
|
140
|
+
@selected_candidate_pair_id = options[:selected_candidate_pair_id]
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
def to_h
|
|
144
|
+
super.merge(
|
|
145
|
+
bytesSent: @bytes_sent,
|
|
146
|
+
bytesReceived: @bytes_received,
|
|
147
|
+
dtlsState: @dtls_state,
|
|
148
|
+
selectedCandidatePairId: @selected_candidate_pair_id
|
|
149
|
+
)
|
|
150
|
+
end
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
class RTCPeerConnectionStats < RTCStats
|
|
154
|
+
attr_reader :data_channels_opened, :data_channels_closed
|
|
155
|
+
|
|
156
|
+
def initialize(options = {})
|
|
157
|
+
super(options.merge(type: :peer_connection))
|
|
158
|
+
@data_channels_opened = options[:data_channels_opened] || 0
|
|
159
|
+
@data_channels_closed = options[:data_channels_closed] || 0
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
def to_h
|
|
163
|
+
super.merge(
|
|
164
|
+
dataChannelsOpened: @data_channels_opened,
|
|
165
|
+
dataChannelsClosed: @data_channels_closed
|
|
166
|
+
)
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
class RTCDataChannelStats < RTCStats
|
|
171
|
+
attr_reader :label, :protocol, :data_channel_identifier, :state, :messages_sent, :bytes_sent, :messages_received,
|
|
172
|
+
:bytes_received
|
|
173
|
+
|
|
174
|
+
def initialize(options = {})
|
|
175
|
+
super(options.merge(type: :data_channel))
|
|
176
|
+
@label = options[:label]
|
|
177
|
+
@protocol = options[:protocol]
|
|
178
|
+
@data_channel_identifier = options[:data_channel_identifier]
|
|
179
|
+
@state = options[:state] || :connecting
|
|
180
|
+
@messages_sent = options[:messages_sent] || 0
|
|
181
|
+
@bytes_sent = options[:bytes_sent] || 0
|
|
182
|
+
@messages_received = options[:messages_received] || 0
|
|
183
|
+
@bytes_received = options[:bytes_received] || 0
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
def to_h
|
|
187
|
+
super.merge(
|
|
188
|
+
label: @label,
|
|
189
|
+
protocol: @protocol,
|
|
190
|
+
dataChannelIdentifier: @data_channel_identifier,
|
|
191
|
+
state: @state,
|
|
192
|
+
messagesSent: @messages_sent,
|
|
193
|
+
bytesSent: @bytes_sent,
|
|
194
|
+
messagesReceived: @messages_received,
|
|
195
|
+
bytesReceived: @bytes_received
|
|
196
|
+
)
|
|
197
|
+
end
|
|
198
|
+
end
|
|
199
|
+
end
|
data/lib/webrtc.rb
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'securerandom'
|
|
4
|
+
|
|
5
|
+
require_relative 'webrtc/version'
|
|
6
|
+
require_relative 'webrtc/errors'
|
|
7
|
+
require_relative 'webrtc/ffi/library'
|
|
8
|
+
require_relative 'webrtc/promise'
|
|
9
|
+
require_relative 'webrtc/session_description'
|
|
10
|
+
require_relative 'webrtc/ice_candidate'
|
|
11
|
+
require_relative 'webrtc/media_stream_track'
|
|
12
|
+
require_relative 'webrtc/media_stream'
|
|
13
|
+
require_relative 'webrtc/rtp_sender'
|
|
14
|
+
require_relative 'webrtc/rtp_receiver'
|
|
15
|
+
require_relative 'webrtc/rtp_transceiver'
|
|
16
|
+
require_relative 'webrtc/ice_transport'
|
|
17
|
+
require_relative 'webrtc/dtls_transport'
|
|
18
|
+
require_relative 'webrtc/sctp_transport'
|
|
19
|
+
require_relative 'webrtc/stats_report'
|
|
20
|
+
require_relative 'webrtc/dtmf_sender'
|
|
21
|
+
require_relative 'webrtc/configuration'
|
|
22
|
+
require_relative 'webrtc/data_channel'
|
|
23
|
+
require_relative 'webrtc/peer_connection'
|
|
24
|
+
|
|
25
|
+
module WebRTC
|
|
26
|
+
class << self
|
|
27
|
+
def init
|
|
28
|
+
result = FFI.webrtc_init
|
|
29
|
+
raise InitializationError, 'Failed to initialize WebRTC' unless result.zero?
|
|
30
|
+
|
|
31
|
+
true
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def cleanup
|
|
35
|
+
FFI.webrtc_cleanup
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
data/webrtc-ruby.gemspec
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'lib/webrtc/version'
|
|
4
|
+
|
|
5
|
+
Gem::Specification.new do |spec|
|
|
6
|
+
spec.name = 'webrtc-ruby'
|
|
7
|
+
spec.version = WebRTC::VERSION
|
|
8
|
+
spec.authors = ['Yudai Takada']
|
|
9
|
+
spec.email = ['t.yudai92@gmail.com']
|
|
10
|
+
|
|
11
|
+
spec.summary = 'WebRTC bindings for Ruby'
|
|
12
|
+
spec.description = 'WebRTC (Web Real-Time Communication) bindings for Ruby, providing real-time audio, video, and data channel capabilities.'
|
|
13
|
+
spec.homepage = 'https://github.com/ydah/webrtc-ruby'
|
|
14
|
+
spec.license = 'MIT'
|
|
15
|
+
spec.required_ruby_version = '>= 3.1.0'
|
|
16
|
+
|
|
17
|
+
spec.metadata['homepage_uri'] = spec.homepage
|
|
18
|
+
spec.metadata['source_code_uri'] = spec.homepage
|
|
19
|
+
spec.metadata['changelog_uri'] = "#{spec.homepage}/blob/main/CHANGELOG.md"
|
|
20
|
+
|
|
21
|
+
spec.files = Dir.chdir(__dir__) do
|
|
22
|
+
`git ls-files -z`.split("\x0").reject do |f|
|
|
23
|
+
(File.expand_path(f) == __FILE__) ||
|
|
24
|
+
f.start_with?(*%w[bin/ test/ spec/ features/ .git .github appveyor Gemfile])
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
spec.bindir = 'exe'
|
|
28
|
+
spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
|
|
29
|
+
spec.require_paths = ['lib']
|
|
30
|
+
|
|
31
|
+
spec.add_dependency 'concurrent-ruby', '~> 1.2'
|
|
32
|
+
spec.add_dependency 'ffi', '~> 1.15'
|
|
33
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: webrtc-ruby
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Yudai Takada
|
|
8
|
+
bindir: exe
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: concurrent-ruby
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - "~>"
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: '1.2'
|
|
19
|
+
type: :runtime
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - "~>"
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: '1.2'
|
|
26
|
+
- !ruby/object:Gem::Dependency
|
|
27
|
+
name: ffi
|
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
|
29
|
+
requirements:
|
|
30
|
+
- - "~>"
|
|
31
|
+
- !ruby/object:Gem::Version
|
|
32
|
+
version: '1.15'
|
|
33
|
+
type: :runtime
|
|
34
|
+
prerelease: false
|
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
36
|
+
requirements:
|
|
37
|
+
- - "~>"
|
|
38
|
+
- !ruby/object:Gem::Version
|
|
39
|
+
version: '1.15'
|
|
40
|
+
description: WebRTC (Web Real-Time Communication) bindings for Ruby, providing real-time
|
|
41
|
+
audio, video, and data channel capabilities.
|
|
42
|
+
email:
|
|
43
|
+
- t.yudai92@gmail.com
|
|
44
|
+
executables: []
|
|
45
|
+
extensions: []
|
|
46
|
+
extra_rdoc_files: []
|
|
47
|
+
files:
|
|
48
|
+
- ".dockerignore"
|
|
49
|
+
- ".rspec"
|
|
50
|
+
- CHANGELOG.md
|
|
51
|
+
- Dockerfile
|
|
52
|
+
- LICENSE
|
|
53
|
+
- README.md
|
|
54
|
+
- Rakefile
|
|
55
|
+
- examples/signaling_server/server.rb
|
|
56
|
+
- examples/simple_data_channel.rb
|
|
57
|
+
- examples/video_call.rb
|
|
58
|
+
- ext/webrtc_ruby/CMakeLists.txt
|
|
59
|
+
- ext/webrtc_ruby/Makefile
|
|
60
|
+
- ext/webrtc_ruby/webrtc_ruby.c
|
|
61
|
+
- ext/webrtc_ruby/webrtc_ruby.h
|
|
62
|
+
- lib/webrtc.rb
|
|
63
|
+
- lib/webrtc/configuration.rb
|
|
64
|
+
- lib/webrtc/data_channel.rb
|
|
65
|
+
- lib/webrtc/dtls_transport.rb
|
|
66
|
+
- lib/webrtc/dtmf_sender.rb
|
|
67
|
+
- lib/webrtc/errors.rb
|
|
68
|
+
- lib/webrtc/ffi/library.rb
|
|
69
|
+
- lib/webrtc/ice_candidate.rb
|
|
70
|
+
- lib/webrtc/ice_transport.rb
|
|
71
|
+
- lib/webrtc/media_stream.rb
|
|
72
|
+
- lib/webrtc/media_stream_track.rb
|
|
73
|
+
- lib/webrtc/peer_connection.rb
|
|
74
|
+
- lib/webrtc/promise.rb
|
|
75
|
+
- lib/webrtc/rtp_receiver.rb
|
|
76
|
+
- lib/webrtc/rtp_sender.rb
|
|
77
|
+
- lib/webrtc/rtp_transceiver.rb
|
|
78
|
+
- lib/webrtc/sctp_transport.rb
|
|
79
|
+
- lib/webrtc/session_description.rb
|
|
80
|
+
- lib/webrtc/stats_report.rb
|
|
81
|
+
- lib/webrtc/version.rb
|
|
82
|
+
- webrtc-ruby.gemspec
|
|
83
|
+
homepage: https://github.com/ydah/webrtc-ruby
|
|
84
|
+
licenses:
|
|
85
|
+
- MIT
|
|
86
|
+
metadata:
|
|
87
|
+
homepage_uri: https://github.com/ydah/webrtc-ruby
|
|
88
|
+
source_code_uri: https://github.com/ydah/webrtc-ruby
|
|
89
|
+
changelog_uri: https://github.com/ydah/webrtc-ruby/blob/main/CHANGELOG.md
|
|
90
|
+
rdoc_options: []
|
|
91
|
+
require_paths:
|
|
92
|
+
- lib
|
|
93
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
94
|
+
requirements:
|
|
95
|
+
- - ">="
|
|
96
|
+
- !ruby/object:Gem::Version
|
|
97
|
+
version: 3.1.0
|
|
98
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
99
|
+
requirements:
|
|
100
|
+
- - ">="
|
|
101
|
+
- !ruby/object:Gem::Version
|
|
102
|
+
version: '0'
|
|
103
|
+
requirements: []
|
|
104
|
+
rubygems_version: 4.0.3
|
|
105
|
+
specification_version: 4
|
|
106
|
+
summary: WebRTC bindings for Ruby
|
|
107
|
+
test_files: []
|