Skip to content

Commit

Permalink
Merge pull request #235 from opentok/devx-5711-selective-stream-feature
Browse files Browse the repository at this point in the history
DEVX-5711 Implement selective stream feature for Archive and Broadcast
  • Loading branch information
superchilled authored Dec 9, 2021
2 parents da77421 + e14c4e4 commit 64c977a
Show file tree
Hide file tree
Showing 11 changed files with 497 additions and 14 deletions.
51 changes: 49 additions & 2 deletions lib/opentok/archive.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,19 +26,26 @@ module OpenTok
# Whether all streams in the archive are recorded to a single file (<code>:composed</code>)
# or to individual files (<code>:individual</code>).
#
# @attr [string] partner_id
# @attr [string] projectId
# The API key associated with the archive.
#
# @attr [string] reason
# For archives with the status "stopped" or "failed", this string describes the
# reason the archive stopped (such as "maximum duration exceeded") or failed.
#
# @attr [string] resolution
# The resolution of the archive (either "640x480", "1280x720", "480x640", or "720x1280").
# This property is only set for composed archives.
#
# @attr [string] session_id
# The session ID of the OpenTok session associated with this archive.
#
# @attr [float] size
# The size of the MP4 file. For archives that have not been generated, this value is set to 0.
#
# @attr [string] streamMode
# Whether streams included in the archive are selected automatically ("auto", the default) or manually ("manual").
#
# @attr [string] status
# The status of the archive, which can be one of the following:
#
Expand Down Expand Up @@ -99,7 +106,7 @@ def delete
# {https://tokbox.com/developer/guides/archiving/layout-control.html Customizing
# the video layout for composed archives}.
#
# @option options [String] :type
# @option options [String] :type
# The layout type. Set this to "bestFit", "pip", "verticalPresentation",
# "horizontalPresentation", "focus", or "custom".
#
Expand Down Expand Up @@ -136,6 +143,46 @@ def layout(opts= {})
@json = @interface.layout(@json['id'], opts)
end

# Adds a stream to currently running composed archive that was started with the
# streamMode set to "manual". For a description of the feature, see
# {https://tokbox.com/developer/rest/#selecting-archive-streams}.
#
# @param [String] stream_id
# The ID for the stream to be added to the archive
#
# @option opts [true, false] :has_audio
# (Boolean, optional) — Whether the composed archive should include the stream's
# audio (true, the default) or not (false).
#
# @option opts [true, false] :has_video
# (Boolean, optional) — Whether the composed archive should include the stream's
# video (true, the default) or not (false).
#
# @raise [OpenTokArchiveError]
# The streamMode for the archive is not set to "manual".
#
# You can call the method repeatedly with add_stream set to the same stream ID, to
# toggle the stream's audio or video in the archive. If you set both has_audio and
# has_video to false, you will get error response.
def add_stream(stream_id, opts = {})
raise OpenTokArchiveError, "stream_mode must be manual in order to add a stream" unless @json['streamMode'] == 'manual'
@interface.add_stream(@json['id'], stream_id, opts)
end

# Removes a stream to currently running composed archive that was started with the
# streamMode set to "manual". For a description of the feature, see
# {https://tokbox.com/developer/rest/#selecting-archive-streams}.
#
# @param [String] stream_id
# The ID for the stream to be removed from the archive
#
# @raise [OpenTokArchiveError]
# The streamMode for the archive is not set to "manual".
def remove_stream(stream_id)
raise OpenTokArchiveError, "stream_mode must be manual in order to remove a stream" unless @json['streamMode'] == 'manual'
@interface.remove_stream(@json['id'], stream_id)
end

# @private ignore
def method_missing(method, *args, &block)
camelized_method = method.to_s.camelize(:lower)
Expand Down
93 changes: 89 additions & 4 deletions lib/opentok/archives.rb
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,19 @@ def initialize(client)
# default) or "1280x720" (HD). This property only applies to composed archives. If you set
# this property and set the outputMode property to "individual", the call the method
# results in an error.
# @option options [String] :streamMode (Optional) Whether streams included in the archive are selected
# automatically ("auto", the default) or manually ("manual"). When streams are selected automatically ("auto"),
# all streams in the session can be included in the archive. When streams are selected manually ("manual"),
# you specify streams to be included based on calls to this REST method
# { https://tokbox.com/developer/rest/#selecting-archive-streams }. You can specify whether a
# stream's audio, video, or both are included in the archive.
# In composed archives, in both automatic and manual modes, the archive composer includes streams based
# on stream prioritization rules { https://tokbox.com/developer/guides/archive-broadcast-layout/#stream-prioritization-rules }.
# Important: this feature is currently available in the Standard environment only.
# @option options [Hash] :layout Specify this to assign the initial layout type for
# the archive. This applies only to composed archives. This is a hash containing three keys:
# <code>:type</code>, <code>:stylesheet<code> and <code>:screenshare_type</code>.
# Valid values for <code>:type</code> are "bestFit" (best fit), "custom" (custom),
# <code>:type</code>, <code>:stylesheet<code> and <code>:screenshare_type</code>.
# Valid values for <code>:type</code> are "bestFit" (best fit), "custom" (custom),
# "horizontalPresentation" (horizontal presentation),
# "pip" (picture-in-picture), and "verticalPresentation" (vertical presentation)).
# If you specify a "custom" layout type, set the <code>:stylesheet</code> key to the
Expand Down Expand Up @@ -171,10 +180,10 @@ def delete_by_id(archive_id)
# {https://tokbox.com/developer/guides/archiving/layout-control.html Customizing
# the video layout for composed archives}.
#
# @param [String] archive_id
# @param [String] archive_id
# The archive ID.
#
# @option options [String] :type
# @option options [String] :type
# The layout type. Set this to "bestFit", "pip", "verticalPresentation",
# "horizontalPresentation", "focus", or "custom".
#
Expand Down Expand Up @@ -226,5 +235,81 @@ def layout(archive_id, options = {})
response = @client.layout_archive(archive_id, options)
(200..300).include? response.code
end

# Adds a stream to currently running composed archive that was started with the
# streamMode set to "manual". For a description of the feature, see
# {https://tokbox.com/developer/rest/#selecting-archive-streams}.
#
# @param [String] archive_id
# The archive ID.
#
# @param [String] stream_id
# The ID for the stream to be added to the archive
#
# @option opts [true, false] :has_audio
# (Boolean, optional) — Whether the composed archive should include the stream's
# audio (true, the default) or not (false).
#
# @option opts [true, false] :has_video
# (Boolean, optional) — Whether the composed archive should include the stream's
# video (true, the default) or not (false).
#
# You can call the method repeatedly with add_stream set to the same stream ID, to
# toggle the stream's audio or video in the archive. If you set both has_audio and
# has_video to false, you will get error response.
#
# @raise [ArgumentError]
# The archive_id parameter is empty.
#
# @raise [ArgumentError]
# The stream_id parameter is empty.
#
# @raise [ArgumentError]
# The has_audio and has_video properties of the options parameter are both set to "false"
#
def add_stream(archive_id, stream_id, options)
raise ArgumentError, "archive_id not provided" if archive_id.to_s.empty?
raise ArgumentError, "stream_id not provided" if stream_id.to_s.empty?
if options.has_key?(:has_audio) && options.has_key?(:has_video)
has_audio = options[:has_audio]
has_video = options[:has_video]
raise ArgumentError, "has_audio and has_video can't both be false" if audio_and_video_options_both_false?(has_audio, has_video)
end
options['add_stream'] = stream_id

@client.select_streams_for_archive(archive_id, options)
end

# Removes a stream from a currently running composed archive that was started with the
# streamMode set to "manual". For a description of the feature, see
# {https://tokbox.com/developer/rest/#selecting-archive-streams}.
#
# @param [String] archive_id
# The archive ID.
#
# @param [String] stream_id
# The ID for the stream to be removed from the archive
#
# @raise [ArgumentError]
# The archive_id parameter id is empty.
#
# @raise [ArgumentError]
# The stream_id parameter is empty.
#
def remove_stream(archive_id, stream_id)
raise ArgumentError, "archive_id not provided" if archive_id.to_s.empty?
raise ArgumentError, "stream_id not provided" if stream_id.to_s.empty?
options = {}
options['remove_stream'] = stream_id

@client.select_streams_for_archive(archive_id, options)
end

private

def audio_and_video_options_both_false?(has_audio, has_video)
has_audio == false && has_video == false
end

end
end
45 changes: 44 additions & 1 deletion lib/opentok/broadcast.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ module OpenTok
# @attr [string] resolution
# The resolution of the broadcast: either "640x480" (SD, the default) or "1280x720" (HD). This property is optional.
#
# @attr [string] streamMode
# Whether streams included in the broadcast are selected automatically ("auto", the default) or manually ("manual").
#
# @attr [Hash] broadcastUrls is defined as follows:
# This object defines the types of broadcast streams you want to start (both HLS and RTMP).
# You can include HLS, RTMP, or both as broadcast streams. If you include RTMP streaming,
Expand Down Expand Up @@ -65,7 +68,7 @@ def stop
# For more information, see
# {https://tokbox.com/developer/guides/broadcast/live-streaming/#configuring-video-layout-for-opentok-live-streaming-broadcasts Configuring video layout for OpenTok live streaming broadcasts}.
#
# @option options [String] :type
# @option options [String] :type
# The layout type. Set this to "bestFit", "pip", "verticalPresentation",
# "horizontalPresentation", "focus", or "custom".
#
Expand Down Expand Up @@ -100,6 +103,46 @@ def layout(opts = {})
@json = @interface.layout(@json['id'], opts)
end

# Adds a stream to currently running broadcast that was started with the
# streamMode set to "manual". For a description of the feature, see
# {https://tokbox.com/developer/rest/#selecting-broadcast-streams}.
#
# @param [String] stream_id
# The ID for the stream to be added to the broadcast
#
# @option opts [true, false] :has_audio
# (Boolean, optional) — Whether the broadcast should include the stream's
# audio (true, the default) or not (false).
#
# @option opts [true, false] :has_video
# (Boolean, optional) — Whether the broadcast should include the stream's
# video (true, the default) or not (false).
#
# @raise [OpenTokBroadcastError]
# The streamMode for the broadcast is not set to "manual".
#
# You can call the method repeatedly with add_stream set to the same stream ID, to
# toggle the stream's audio or video in the broadcast. If you set both has_audio and
# has_video to false, you will get error response.
def add_stream(stream_id, opts = {})
raise OpenTokBroadcastError, "stream_mode must be manual in order to add a stream" unless @json['streamMode'] == 'manual'
@interface.add_stream(@json['id'], stream_id, opts)
end

# Removes a stream to currently running broadcast that was started with the
# streamMode set to "manual". For a description of the feature, see
# {https://tokbox.com/developer/rest/#selecting-broadcast-streams}.
#
# @param [String] stream_id
# The ID for the stream to be removed from the broadcast
#
# @raise [OpenTokBroadcastError]
# The streamMode for the broadcast is not set to "manual".
def remove_stream(stream_id)
raise OpenTokBroadcastError, "stream_mode must be manual in order to add a stream" unless @json['streamMode'] == 'manual'
@interface.remove_stream(@json['id'], stream_id)
end

# @private ignore
def method_missing(method, *args, &block)
camelized_method = method.to_s.camelize(:lower)
Expand Down
92 changes: 88 additions & 4 deletions lib/opentok/broadcasts.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ def initialize(client)
#
# @option options [Hash] :layout Specify this to assign the initial layout type for
# the broadcast. This is a hash containing three keys:
# <code>:type</code>, <code>:stylesheet<code> and <code>:screenshare_type</code>.
# Valid values for <code>:type</code> are "bestFit" (best fit), "custom" (custom),
# <code>:type</code>, <code>:stylesheet<code> and <code>:screenshare_type</code>.
# Valid values for <code>:type</code> are "bestFit" (best fit), "custom" (custom),
# "horizontalPresentation" (horizontal presentation),
# "pip" (picture-in-picture), and "verticalPresentation" (vertical presentation)).
# If you specify a "custom" layout type, set the <code>:stylesheet</code> key to the
Expand Down Expand Up @@ -55,11 +55,21 @@ def initialize(client)
# @option options [string] resolution
# The resolution of the broadcast: either "640x480" (SD, the default) or "1280x720" (HD).
#
# @option options [String] :streamMode (Optional) Whether streams included in the broadcast are selected
# automatically ("auto", the default) or manually ("manual"). When streams are selected automatically ("auto"),
# all streams in the session can be included in the broadcast. When streams are selected manually ("manual"),
# you specify streams to be included based on calls to this REST method
# { https://tokbox.com/developer/rest/#selecting-broadcast-streams }. You can specify whether a
# stream's audio, video, or both are included in the broadcast.
# For both automatic and manual modes, the broadcast composer includes streams based
# on stream prioritization rules { https://tokbox.com/developer/guides/archive-broadcast-layout/#stream-prioritization-rules }.
# Important: this feature is currently available in the Standard environment only.
#
# @return [Broadcast] The broadcast object, which includes properties defining the broadcast,
# including the broadcast ID.
#
# @raise [OpenTokBroadcastError] The broadcast could not be started. The request was invalid or broadcast already started
# @raise [OpenTokAuthenticationError] Authentication failed while starting an archive.
# @raise [OpenTokAuthenticationError] Authentication failed while starting an broadcast.
# Invalid API key.
# @raise [OpenTokError] OpenTok server error.
def create(session_id, options = {})
Expand Down Expand Up @@ -111,7 +121,7 @@ def stop(broadcast_id)
# @param [String] broadcast_id
# The broadcast ID.
#
# @option options [String] :type
# @option options [String] :type
# The layout type. Set this to "bestFit", "pip", "verticalPresentation",
# "horizontalPresentation", "focus", or "custom".
#
Expand Down Expand Up @@ -159,6 +169,80 @@ def layout(broadcast_id, options = {})
(200..300).include? response.code
end

# Adds a stream to currently running broadcast that was started with the
# streamMode set to "manual". For a description of the feature, see
# {https://tokbox.com/developer/rest/#selecting-broadcast-streams}.
#
# @param [String] broadcast_id
# The broadcast ID.
#
# @param [String] stream_id
# The ID for the stream to be added to the broadcast
#
# @option opts [true, false] :has_audio
# (Boolean, optional) — Whether the broadcast should include the stream's
# audio (true, the default) or not (false).
#
# @option opts [true, false] :has_video
# (Boolean, optional) — Whether the broadcast should include the stream's
# video (true, the default) or not (false).
#
# You can call the method repeatedly with add_stream set to the same stream ID, to
# toggle the stream's audio or video in the broadcast. If you set both has_audio and
# has_video to false, you will get error response.
#
# @raise [ArgumentError]
# The broadcast_id parameter is empty.
#
# @raise [ArgumentError]
# The stream_id parameter is empty.
#
# @raise [ArgumentError]
# The has_audio and has_video properties of the options parameter are both set to "false"
#
def add_stream(broadcast_id, stream_id, options)
raise ArgumentError, "broadcast_id not provided" if broadcast_id.to_s.empty?
raise ArgumentError, "stream_id not provided" if stream_id.to_s.empty?
if options.has_key?(:has_audio) && options.has_key?(:has_video)
has_audio = options[:has_audio]
has_video = options[:has_video]
raise ArgumentError, "has_audio and has_video can't both be false" if audio_and_video_options_both_false?(has_audio, has_video)
end
options['add_stream'] = stream_id

@client.select_streams_for_broadcast(broadcast_id, options)
end

# Removes a stream from a currently running broadcast that was started with the
# streamMode set to "manual". For a description of the feature, see
# {https://tokbox.com/developer/rest/#selecting-broadcast-streams}.
#
# @param [String] broadcast_id
# The broadcast ID.
#
# @param [String] stream_id
# The ID for the stream to be removed from the broadcast
#
# @raise [ArgumentError]
# The broadcast_id parameter id is empty.
#
# @raise [ArgumentError]
# The stream_id parameter is empty.
#
def remove_stream(broadcast_id, stream_id)
raise ArgumentError, "broadcast_id not provided" if broadcast_id.to_s.empty?
raise ArgumentError, "stream_id not provided" if stream_id.to_s.empty?
options = {}
options['remove_stream'] = stream_id

@client.select_streams_for_broadcast(broadcast_id, options)
end

private

def audio_and_video_options_both_false?(has_audio, has_video)
has_audio == false && has_video == false
end

end
end
Loading

0 comments on commit 64c977a

Please sign in to comment.