public void GenerateTokenWithExpireTimeTest() { OpenTok opentok = new OpenTok(apiKey, apiSecret); double expireTime = OpenTokUtils.GetCurrentUnixTimeStamp() + 10; String sessionId = "1_MX4xMjM0NTZ-flNhdCBNYXIgMTUgMTQ6NDI6MjMgUERUIDIwMTR-MC40OTAxMzAyNX4"; string token = opentok.GenerateToken(sessionId, expireTime: expireTime); Assert.NotNull(token); var data = CheckToken(token, apiKey); Assert.Equal(data["partner_id"], apiKey.ToString()); Assert.NotNull(data["sig"]); Assert.NotNull(data["create_time"]); Assert.NotNull(data["nonce"]); Assert.Equal(data["role"], Role.PUBLISHER.ToString()); Assert.Equal(data["expire_time"], ((long)expireTime).ToString()); }
/** * Starts archiving an OpenTok session. * * <p> * Clients must be actively connected to the OpenTok session for you to successfully start * recording an archive. * <p> * You can only record one archive at a time for a given session. You can only record * archives of sessions that uses the OpenTok Media Router (sessions with the media mode set * to routed); you cannot archive sessions with the media mode set to relayed. * <p> * Note that you can have the session be automatically archived by setting the archiveMode * parameter of the OpenTok.CreateSession() method to ArchiveMode.ALWAYS. * * @param sessionId The session ID of the OpenTok session to archive. * * @param name The name of the archive. You can use this name to identify the archive. It is * a property of the Archive object, and it is a property of archive-related events in the * OpenTok client libraries. * * @param hasVideo Whether the archive will record video (true) or not (false). The default * value is true (video is recorded). If you set both <code>hasAudio</code> and * <code>hasVideo</code> to false, the call to the <code>StartArchive()</code> method * results in an error. * * @param hasAudio Whether the archive will record audio (true) or not (false). The default * value is true (audio is recorded). If you set both <code>hasAudio</code> and * <code>hasVideo</code> to false, the call to the <code>StartArchive()</code> method * results in an error. * * @param outputMode Whether all streams in the archive are recorded to a single file * (<code>OutputMode.COMPOSED</code>, the default) or to individual files * (<code>OutputMode.INDIVIDUAL</code>). * * @return The Archive object. This object includes properties defining the archive, * including the archive ID. */ public async Task <Archive> StartArchive(string sessionId, string name = "", bool hasVideo = true, bool hasAudio = true, OutputMode outputMode = OutputMode.COMPOSED) { if (String.IsNullOrEmpty(sessionId)) { throw new OpenTokArgumentException("Session not valid"); } string url = string.Format("v2/partner/{0}/archive", this.ApiKey); var headers = new Dictionary <string, string> { { "Content-type", "application/json" } }; var data = new Dictionary <string, object>() { { "sessionId", sessionId }, { "name", name }, { "hasVideo", hasVideo }, { "hasAudio", hasAudio }, { "outputMode", outputMode.ToString().ToLower() } }; string response = await Client.Post(url, headers, data); return(OpenTokUtils.GenerateArchive(response, ApiKey, ApiSecret, OpenTokServer)); }
/** * Starts archiving an OpenTok 2.0 session. * * <p> * Clients must be actively connected to the OpenTok session for you to successfully start * recording an archive. * <p> * You can only record one archive at a time for a given session. You can only record * archives of sessions that uses the OpenTok Media Router; you cannot archive peer-to-peer * sessions. * * @param sessionId The session ID of the OpenTok session to archive. * * @param name The name of the archive. You can use this name to identify the archive. It is * a property of the Archive object, and it is a property of archive-related events in the * OpenTok client libraries. * * @return The Archive object. This object includes properties defining the archive, * including the archive ID. */ public Archive StartArchive(string sessionId, string name = "") { if (String.IsNullOrEmpty(sessionId)) { throw new OpenTokArgumentException("Session not valid"); } string url = string.Format("v2/partner/{0}/archive", this.ApiKey); var headers = new Dictionary <string, string> { { "Content-type", "application/json" } }; var data = new Dictionary <string, object>() { { "sessionId", sessionId }, { "name", name } }; string response = Client.Post(url, headers, data); return(OpenTokUtils.GenerateArchive(response, ApiKey, ApiSecret, OpenTokServer)); }
/** * Creates a new OpenTok session. * <p> * OpenTok sessions do not expire. However, authentication tokens do expire (see the * generateToken() method). Also note that sessions cannot explicitly be destroyed. * <p> * A session ID string can be up to 255 characters long. * <p> * Calling this method results in an OpenTokException in the event of an error. * Check the error message for details. * * You can also create a session using the * <a href="http://www.tokbox.com/opentok/api/#session_id_production">OpenTok * REST API</a> or the <a href="https://dashboard.tokbox.com/projects">OpenTok * dashboard</a>. * * @param location (String) An IP address that the OpenTok servers will use to * situate the session in its global network. If you do not set a location hint, * the OpenTok servers will be based on the first client connecting to the session. * * @param mediaMode Whether the session will transmit streams using the * OpenTok Media Router (<code>MediaMode.ROUTED</code>) or not * (<code>MediaMode.RELAYED</code>). By default, the setting is * <code>MediaMode.RELAYED</code>. * <p> * With the <code>mediaMode</code> parameter set to <code>MediaMode.RELAYED</code>, the * session will attempt to transmit streams directly between clients. If clients cannot * connect due to firewall restrictions, the session uses the OpenTok TURN server to relay * streams. * <p> * The <a href="https://tokbox.com/opentok/tutorials/create-session/#media-mode" * target="_top">OpenTok Media Router</a> provides the following benefits: * * <ul> * <li>The OpenTok Media Router can decrease bandwidth usage in multiparty sessions. * (When the <code>mediaMode</code> parameter is set to * <code>MediaMode.ROUTED</code>, each client must send a separate audio-video stream * to each client subscribing to it.)</li> * <li>The OpenTok Media Router can improve the quality of the user experience through * <a href="https://tokbox.com/platform/fallback" target="_top">audio fallback and video * recovery</a>. With these features, if a client's connectivity degrades to a degree * that it does not support video for a stream it's subscribing to, the video is dropped * on that client (without affecting other clients), and the client receives audio only. * If the client's connectivity improves, the video returns.</li> * <li>The OpenTok Media Router supports the * <a href="http://tokbox.com/opentok/tutorials/archiving" target="_top">archiving</a> * feature, which lets you record, save, and retrieve OpenTok sessions.</li> * </ul> * * @param archiveMode Whether the session is automatically archived * (<code>ArchiveMode.ALWAYS</code>) or not (<code>ArchiveMode.MANUAL</code>). By default, * the setting is <code>ArchiveMode.MANUAL</code>, and you must call the * StartArchive() method of the OpenTok object to start archiving. To archive the session * (either automatically or not), you must set the mediaMode parameter to * <code>MediaMode.ROUTED</code>. * * @return A Session object representing the new session. The <code>Id</code> property of * the Session is the session ID, which uniquely identifies the session. You will use * this session ID in the client SDKs to identify the session. For example, when using the * OpenTok.js library, use the session ID when calling the * <a href="http://tokbox.com/opentok/libraries/client/js/reference/OT.html#initSession"> * OT.initSession()</a> method (to initialize an OpenTok session). */ public async Task <Session> CreateSession(string location = "", MediaMode mediaMode = MediaMode.RELAYED, ArchiveMode archiveMode = ArchiveMode.MANUAL) { if (!OpenTokUtils.TestIpAddress(location)) { throw new OpenTokArgumentException(string.Format("Location {0} is not a valid IP address", location)); } if (archiveMode == ArchiveMode.ALWAYS && mediaMode != MediaMode.ROUTED) { throw new OpenTokArgumentException("A session with always archive mode must also have the routed media mode."); } string preference = (mediaMode == MediaMode.RELAYED) ? "enabled" : "disabled"; var headers = new Dictionary <string, string> { { "Content-type", "application/x-www-form-urlencoded" } }; var data = new Dictionary <string, object> { { "location", location }, { "p2p.preference", preference }, { "archiveMode", archiveMode.ToString().ToLower() } }; var response = await Client.Post("session/create", headers, data); var xmlDoc = XDocument.Parse(response); if (!xmlDoc.Descendants("session_id").Any()) { throw new OpenTokWebException("Session could not be provided. Are ApiKey and ApiSecret correctly set?"); } var sessionId = xmlDoc.Descendants("session_id").First().Value; var apiKey = Convert.ToInt32(xmlDoc.Descendants("partner_id").First().Value); return(new Session(sessionId, apiKey, ApiSecret, location, mediaMode, archiveMode)); }
/// <summary> /// Starts archiving an OpenTok session. /// <para> /// Clients must be actively connected to the OpenTok session for you to successfully start /// recording an archive. /// </para> /// <para> /// You can only record one archive at a time for a given session. You can only record /// archives of sessions that uses the OpenTok Media Router (sessions with the media mode set /// to routed); you cannot archive sessions with the media mode set to relayed. /// </para> /// <para> /// Note that you can have the session be automatically archived by setting the archiveMode /// parameter of the <see cref="CreateSession"/> method to <see cref="ArchiveMode.ALWAYS"/>. /// </para> /// </summary> /// <param name="sessionId"> /// The session ID of the OpenTok session to archive. /// </param> /// <param name="name"> /// The name of the archive. You can use this name to identify the archive. It is a property /// of the Archive object, and it is a property of archive-related events in the OpenTok client /// libraries. /// </param> /// <param name="hasVideo"> /// Whether the archive will record video (true) or not (false). The default value is true /// (video is recorded). If you set both <paramref name="hasAudio"/> and <paramref name="hasVideo"/> /// to false, the call to the <see cref="StartArchive"/> method results in an error. /// </param> /// <param name="hasAudio"> /// Whether the archive will record audio (true) or not (false). The default value is true /// (audio is recorded). If you set both <paramref name="hasAudio"/> and <paramref name="hasVideo"/> /// to false, the call to the <see cref="StartArchive"/> method results in an error. /// </param> /// <param name="outputMode"> /// Whether all streams in the archive are recorded to a single file (<see cref="OutputMode.COMPOSED"/>, /// the default) or to individual files (<see cref="OutputMode.INDIVIDUAL"/>). /// </param> /// <param name="resolution"> /// The resolution for the archive. The default for <see cref="OutputMode.COMPOSED"/> is "640x480". /// You cannot specify the resolution for <see cref="OutputMode.INDIVIDUAL"/>. /// </param> /// <param name="layout"> /// The layout that you want to use for your archive. If type is set to <see cref="LayoutType.custom"/> /// you must provide a StyleSheet string to Vonage how to layout your archive. /// </param> /// <returns> /// The Archive object. This object includes properties defining the archive, including the archive ID. /// </returns> public Archive StartArchive(string sessionId, string name = "", bool hasVideo = true, bool hasAudio = true, OutputMode outputMode = OutputMode.COMPOSED, string resolution = null, ArchiveLayout layout = null) { if (String.IsNullOrEmpty(sessionId)) { throw new OpenTokArgumentException("Session not valid"); } string url = string.Format("v2/project/{0}/archive", this.ApiKey); var headers = new Dictionary <string, string> { { "Content-type", "application/json" } }; var data = new Dictionary <string, object>() { { "sessionId", sessionId }, { "name", name }, { "hasVideo", hasVideo }, { "hasAudio", hasAudio }, { "outputMode", outputMode.ToString().ToLowerInvariant() } }; if (!String.IsNullOrEmpty(resolution) && outputMode.Equals(OutputMode.INDIVIDUAL)) { throw new OpenTokArgumentException("Resolution can't be specified for Individual Archives"); } else if (!String.IsNullOrEmpty(resolution) && outputMode.Equals(OutputMode.COMPOSED)) { data.Add("resolution", resolution); } if (layout != null) { if (layout?.Type == LayoutType.custom && string.IsNullOrEmpty(layout?.StyleSheet) || layout?.Type != LayoutType.custom && !string.IsNullOrEmpty(layout?.StyleSheet)) { throw new OpenTokArgumentException("Could not set layout, stylesheet must be set if and only if type is custom"); } data.Add("layout", layout); } string response = Client.Post(url, headers, data); return(OpenTokUtils.GenerateArchive(response, ApiKey, ApiSecret, OpenTokServer)); }
/** * Use this method to start a live streaming for an OpenTok session. * This broadcasts the session to an HLS (HTTP live streaming) or to RTMP streams. * <p> * To successfully start broadcasting a session, at least one client must be connected to the session. * <p> * You can only have one active live streaming broadcast at a time for a session * (however, having more than one would not be useful). * The live streaming broadcast can target one HLS endpoint and up to five RTMP servers simulteneously for a session. * You can only start live streaming for sessions that use the OpenTok Media Router (with the media mode set to routed); * you cannot use live streaming with sessions that have the media mode set to relayed OpenTok Media Router. See * <a href="https://tokbox.com/developer/guides/create-session/#media-mode">The OpenTok Media Router and media modes.</a> * <p> * For more information on broadcasting, see the * <a href="https://tokbox.com/developer/guides/broadcast/">Broadcast developer guide.</a> * * @param sessionId The session ID corresponding to the session. * * @param properties This BroadcastProperties object defines options for the broadcast. * * @return The Broadcast object. This object includes properties defining the archive, including the archive ID. */ public Broadcast StartBroadcast(string sessionId, Boolean hls = true, List <Rtmp> rtmpList = null, string resolution = null, int maxDuration = 7200, BroadcastLayout layout = null) { if (String.IsNullOrEmpty(sessionId)) { throw new OpenTokArgumentException("Session not valid"); } if (!String.IsNullOrEmpty(resolution) && resolution != "640x480" && resolution != "1280x720") { throw new OpenTokArgumentException("Resolution value must be either 640x480 (SD) or 1280x720 (HD)."); } if (maxDuration < 60 || maxDuration > 36000) { throw new OpenTokArgumentException("MaxDuration value must be between 60 and 36000 (inclusive)."); } if (rtmpList != null && rtmpList.Count() >= 5) { throw new OpenTokArgumentException("Cannot add more than 5 RTMP properties"); } string url = string.Format("v2/project/{0}/broadcast", this.ApiKey); var headers = new Dictionary <string, string> { { "Content-type", "application/json" } }; var outputs = new Dictionary <string, object>(); if (hls) { outputs.Add("hls", new Object()); } if (rtmpList != null) { outputs.Add("rtmp", rtmpList); } var data = new Dictionary <string, object>() { { "sessionId", sessionId }, { "maxDuration", maxDuration }, { "outputs", outputs } }; if (!String.IsNullOrEmpty(resolution)) { data.Add("resolution", resolution); } if (layout != null) { if ((layout.Type.Equals(BroadcastLayout.LayoutType.Custom) && String.IsNullOrEmpty(layout.Stylesheet)) || (!layout.Type.Equals(BroadcastLayout.LayoutType.Custom) && !String.IsNullOrEmpty(layout.Stylesheet))) { throw new OpenTokArgumentException("Could not set the layout. Either an invalid JSON or an invalid layout options."); } else { if (layout.Type.Equals(BroadcastLayout.LayoutType.Custom)) { data.Add("layout", layout); } else { data.Add("layout", new { type = OpenTokUtils.convertToCamelCase(layout.Type.ToString()) }); } } } string response = Client.Post(url, headers, data); return(OpenTokUtils.GenerateBroadcast(response, ApiKey, ApiSecret, OpenTokServer)); }
public MainModule(OpenTokService opentokService) { Get["/"] = _ => View["index"]; Get["/host"] = _ => { dynamic locals = new ExpandoObject(); locals.ApiKey = opentokService.OpenTok.ApiKey.ToString(); locals.SessionId = opentokService.Session.Id; locals.Token = opentokService.Session.GenerateToken(Role.PUBLISHER, 0, null, new List <string> (new string[] { "focus" })); locals.InitialBroadcastId = opentokService.broadcastId; locals.FocusStreamId = opentokService.focusStreamId; locals.InitialLayout = OpenTokUtils.convertToCamelCase(opentokService.layout.ToString()); return(View["host", locals]); }; Get["/participant"] = _ => { dynamic locals = new ExpandoObject(); locals.ApiKey = opentokService.OpenTok.ApiKey.ToString(); locals.SessionId = opentokService.Session.Id; locals.Token = opentokService.Session.GenerateToken(); locals.FocusStreamId = opentokService.focusStreamId; locals.Layout = OpenTokUtils.convertToCamelCase(opentokService.layout.ToString()); return(View["participant", locals]); }; Post["/start"] = _ => { bool horizontal = Request.Form["layout"] == "horizontalPresentation"; BroadcastLayout layoutType = new BroadcastLayout(horizontal ? BroadcastLayout.LayoutType.HorizontalPresentation : BroadcastLayout.LayoutType.VerticalPresentation); int maxDuration = 7200; if (Request.Form["maxDuration"] != null) { maxDuration = int.Parse(Request.Form["maxDuration"]); } Broadcast broadcast = opentokService.OpenTok.StartBroadcast( opentokService.Session.Id, hls: true, rtmpList: null, resolution: Request.Form["resolution"], maxDuration: maxDuration, layout: layoutType ); opentokService.broadcastId = broadcast.Id.ToString(); return(broadcast); }; Get["/stop/{id}"] = parameters => { Broadcast broadcast = opentokService.OpenTok.StopBroadcast(parameters.id); opentokService.broadcastId = ""; return(broadcast); }; Get["/broadcast"] = _ => { if (!String.IsNullOrEmpty(opentokService.broadcastId)) { try { Broadcast broadcast = opentokService.OpenTok.GetBroadcast(opentokService.broadcastId); if (broadcast.Status == Broadcast.BroadcastStatus.STARTED) { return(Response.AsRedirect(broadcast.Hls)); } else { return(Response.AsText("Broadcast not in progress.")); } } catch (Exception ex) { return(Response.AsText("Could not get broadcast " + opentokService.broadcastId + ". Exception Message: " + ex.Message)); } } else { return(Response.AsText("There's no broadcast running right now.")); } }; Get["/broadcast/{id}/layout/{layout}"] = parameters => { bool horizontal = parameters.layout == "horizontalPresentation"; BroadcastLayout layout = new BroadcastLayout(horizontal ? BroadcastLayout.LayoutType.HorizontalPresentation : BroadcastLayout.LayoutType.VerticalPresentation); opentokService.OpenTok.SetBroadcastLayout(parameters.id, layout); return(HttpStatusCode.OK); }; Post["/focus"] = _ => { string focusStreamId = Request.Form["focus"]; opentokService.focusStreamId = focusStreamId; StreamList streamList = opentokService.OpenTok.ListStreams(opentokService.Session.Id); List <StreamProperties> streamPropertiesList = new List <StreamProperties>(); foreach (Stream stream in streamList) { StreamProperties streamProperties = new StreamProperties(stream.Id, null); if (focusStreamId.Equals(stream.Id)) { streamProperties.addLayoutClass("focus"); } streamPropertiesList.Add(streamProperties); } opentokService.OpenTok.SetStreamClassLists(opentokService.Session.Id, streamPropertiesList); return(HttpStatusCode.OK); }; }