public ActionResult MusicPlayer(string albumId) { AlbumPlayerViewModel model = new AlbumPlayerViewModel(); model.MediaId = albumId; WebTranscoderProfile profile = GetProfile(Connections.Current.MASStreamControl, Settings.ActiveSettings.DefaultAudioProfile); model.Tracks = Connections.Current.MAS.GetMusicTracksDetailedForAlbum(Settings.ActiveSettings.MusicProvider, albumId); return(CreatePlayer(Connections.Current.MASStreamControl, model, StreamTarget.GetAudioTargets(), profile, true)); }
public ActionResult MusicPlayer(string albumId) { AlbumPlayerViewModel model = new AlbumPlayerViewModel(); model.MediaId = albumId; model.ContinuationId = "playlist-" + randomGenerator.Next(100000, 999999).ToString(); WebTranscoderProfile profile = GetProfile(Connections.Current.MASStreamControl, Configuration.StreamingPlatforms.GetDefaultProfileForUserAgent(StreamingProfileType.Audio, Request.UserAgent)); model.Tracks = Connections.Current.MAS.GetMusicTracksDetailedForAlbum(Settings.ActiveSettings.MusicProvider, albumId); return(CreatePlayer(Connections.Current.MASStreamControl, model, StreamTarget.GetAudioTargets(), profile, true)); }
private string ActuallyStartHttpLiveStream(WebMediaType type, string itemId, WebTranscoderProfile profile, int starttime, string continuationId) { // Get identifier and continuationId continuationId = continuationId ?? "hls-" + randomGenerator.Next(10000, 99999).ToString(); bool alreadyRunning = RunningStreams.ContainsKey(continuationId); string identifier = alreadyRunning ? RunningStreams[continuationId] : "webmediaportal-" + randomGenerator.Next(10000, 99999); Log.Debug("Requested HLS file for continuationId={0}; running={1}; identifier={2}", continuationId, alreadyRunning, identifier); // We only need to start the stream if this is the first request for this file string url; if (!alreadyRunning) { Log.Debug("Starting HLS stream type={0}; itemId={1}; profile={2}; starttime={3}; continuationId={4}; identifier={5}", type, itemId, profile.Name, starttime, continuationId, identifier); Log.Debug("Stream is for user {0} from host {1}, has identifier {2} and timeout {3}s", HttpContext.User.Identity.Name, Request.UserHostAddress, identifier, STREAM_TIMEOUT_HTTPLIVE); // Start the stream string clientDescription = String.Format("WebMediaPortal (user {0})", HttpContext.User.Identity.Name); using (var scope = WCFClient.EnterOperationScope(GetStreamControl(type))) { WCFClient.SetHeader("forwardedFor", HttpContext.Request.UserHostAddress); if (!GetStreamControl(type).InitStream((WebMediaType)type, GetProvider(type), itemId, clientDescription, identifier, STREAM_TIMEOUT_HTTPLIVE)) { Log.Error("InitStream for HLS failed"); return(null); } } // Get stream URL url = GetStreamControl(type).StartStream(identifier, profile.Name, starttime); if (String.IsNullOrEmpty(url)) { Log.Error("StartStream for HLS failed"); return(null); } Log.Debug("Started HLS stream successfully at {0}", url); RunningStreams[continuationId] = identifier; HttpLiveUrls[identifier] = url; } return(identifier); }
// // Player protected ActionResult CreatePlayer(IWebStreamingService streamControl, PlayerViewModel model, List <StreamTarget> targets, WebTranscoderProfile profile, bool album) { // save stream request if (!PlayerOpenedBy.Contains(Request.UserHostAddress)) { PlayerOpenedBy.Add(Request.UserHostAddress); } // get view properties VideoPlayer player = targets.First(x => profile.Targets.Contains(x.Name)).Player; string viewName = Enum.GetName(typeof(VideoPlayer), player) + (album ? "Album" : "") + "Player"; // generate view var supportedTargets = Configuration.StreamingPlatforms.GetValidTargetsForUserAgent(Request.UserAgent).Intersect(targets.Select(x => x.Name)); model.Transcoders = ProfileModel.GetProfilesForTargets(streamControl, supportedTargets).Select(x => x.Name); model.Transcoder = profile.Name; model.TranscoderProfile = profile; model.Player = player; model.PlayerViewName = viewName; Log.Debug("Created player with size={0} view={1} transcoder={2} url={3}", model.Size, viewName, profile.Name, model.URL); return(PartialView("Player", model)); }
private ActionResult GenerateHttpLiveStream(WebMediaType type, string itemId, int fileindex, WebTranscoderProfile profile, int starttime, string continuationId) { string identifier = ActuallyStartHttpLiveStream(type, itemId, fileindex, profile, starttime, continuationId); if (identifier == null) { return(new HttpStatusCodeResult((int)HttpStatusCode.InternalServerError)); } // Return the actual file contents GetStreamControl(type).AuthorizeRemoteHostForStreaming(HttpContext.Request.UserHostAddress); if (GetStreamMode() == StreamType.Direct) { Log.Debug("HLS: Using Direct streaming mode and redirecting to playlist at {0}", HttpLiveUrls[identifier]); return(Redirect(HttpLiveUrls[identifier])); } else { ProxyHttpLiveIndex(identifier, HttpLiveUrls[identifier]); return(new EmptyResult()); } }
private ActionResult GenerateStream(WebMediaType type, string itemId, int fileindex, string transcoder, int starttime, string continuationId) { // Check if there is actually a player requested for this stream if (!IsUserAuthenticated()) { Log.Warn("User {0} (host {1}) requested a stream but isn't authenticated - denying access to stream", HttpContext.User.Identity.Name, Request.UserHostAddress); return(new HttpUnauthorizedResult()); } // Load and validate profile WebTranscoderProfile profile = GetStreamControl(type).GetTranscoderProfileByName(transcoder); if (profile == null) { Log.Error("Requested stream for non-existing profile '{0}', other parameters type={1}; itemId={2}; starttime={3}; continuationId={4}", transcoder, type, itemId, starttime, continuationId); return(new HttpNotFoundResult()); } // Delegate to HLS streaming if needed if (profile.HasVideoStream && StreamTarget.GetVideoTargets().First(x => profile.Targets.Contains(x.Name)).Player == VideoPlayer.HLS) { return(GenerateHttpLiveStream(type, itemId, fileindex, profile, starttime, continuationId)); } // Generate random identifier, and continuationId if needed string identifier = "webmediaportal-" + randomGenerator.Next(10000, 99999); continuationId = continuationId ?? "none-provided-" + randomGenerator.Next(10000, 99999).ToString(); // Kill previous stream, but only if we expect it to be still running (avoid useless calls in non-seek and proxied cases) if (RunningStreams.ContainsKey(continuationId)) { Log.Debug("Killing off old stream for continuationId {0} with identifier {1} first", continuationId, RunningStreams[continuationId]); GetStreamControl(type).FinishStream(RunningStreams[continuationId]); } // Check stream mode, generate timeout setting and dump all info we got StreamType streamMode = GetStreamMode(); int timeout = streamMode == StreamType.Direct ? STREAM_TIMEOUT_DIRECT : STREAM_TIMEOUT_PROXY; Log.Debug("Starting stream type={0}; itemId={1}; index={2}; transcoder={3}; starttime={4}; continuationId={5}", type, itemId, fileindex, transcoder, starttime, continuationId); Log.Debug("Stream is for user {0} from host {1}, has identifier {2} and is using mode {3} with timeout {4}s", HttpContext.User.Identity.Name, Request.UserHostAddress, identifier, streamMode, timeout); // Start the stream string clientDescription = String.Format("WebMediaPortal (user {0})", HttpContext.User.Identity.Name); using (var scope = WCFClient.EnterOperationScope(GetStreamControl(type))) { WCFClient.SetHeader("forwardedFor", HttpContext.Request.UserHostAddress); if (!GetStreamControl(type).InitStream((WebMediaType)type, GetProvider(type), itemId, fileindex, clientDescription, identifier, timeout)) { Log.Error("InitStream failed"); return(new HttpStatusCodeResult((int)HttpStatusCode.InternalServerError)); } } // Save stream RunningStreams[continuationId] = identifier; string url = GetStreamControl(type).StartStream(identifier, transcoder, starttime); if (String.IsNullOrEmpty(url)) { Log.Error("StartStream failed"); return(new HttpStatusCodeResult((int)HttpStatusCode.InternalServerError)); } Log.Debug("Stream started successfully and is at {0}", url); // Do the actual streaming if (streamMode == StreamType.Proxied) { GetStreamControl(type).AuthorizeStreaming(); ProxyStream(url); } else if (streamMode == StreamType.Direct) { GetStreamControl(type).AuthorizeRemoteHostForStreaming(HttpContext.Request.UserHostAddress); return(Redirect(url)); } // Kill stream (doesn't matter much if this doesn't happen, WSS kills streams automatically nowadays) Log.Debug("Finished stream {0}", identifier); RunningStreams.Remove(continuationId); if (!GetStreamControl(type).FinishStream(identifier)) { Log.Error("FinishStream failed"); } return(new EmptyResult()); }
// // Player protected ActionResult CreatePlayer(IWebStreamingService streamControl, PlayerViewModel model, List <StreamTarget> targets, WebTranscoderProfile profile, bool album) { // save stream request if (!PlayerOpenedBy.Contains(Request.UserHostAddress)) { PlayerOpenedBy.Add(Request.UserHostAddress); } // get all transcoder profiles List <string> profiles = new List <string>(); foreach (StreamTarget target in targets) { profiles = profiles.Concat(streamControl.GetTranscoderProfilesForTarget(target.Name).Select(x => x.Name)).Distinct().ToList(); } // get view properties VideoPlayer player = targets.First(x => profile.Targets.Contains(x.Name)).Player; string viewName = Enum.GetName(typeof(VideoPlayer), player) + (album ? "Album" : "") + "Player"; // generate view model.Transcoders = profiles; model.Transcoder = profile.Name; model.TranscoderProfile = profile; model.Player = player; model.PlayerViewName = viewName; Log.Debug("Created player with size={0} view={1} transcoder={2} url={3}", model.Size, viewName, profile.Name, model.URL); return(PartialView("Player", model)); }
public ActionResult Player(WebStreamMediaType type, string itemId, bool video = true) { // get transcoding profile IWebStreamingService streamControl = GetStreamControl(type); WebTranscoderProfile profile = null; if (Request.QueryString["transcoder"] != null) { profile = GetStreamControl(type).GetTranscoderProfileByName(Request.QueryString["transcoder"]); } if (Request.Form["transcoder"] != null) { profile = GetStreamControl(type).GetTranscoderProfileByName(Request.Form["transcoder"]); } if (profile == null) { string defaultName = ""; if (type == WebStreamMediaType.TV || type == WebStreamMediaType.Recording) { defaultName = Settings.ActiveSettings.DefaultTVProfile; } else if (video) { defaultName = Settings.ActiveSettings.DefaultMediaProfile; } else { defaultName = Settings.ActiveSettings.DefaultAudioProfile; } profile = GetStreamControl(type).GetTranscoderProfileByName(defaultName); } // get all transcoder profiles List <StreamTarget> targets = video ? StreamTarget.GetVideoTargets() : StreamTarget.GetAudioTargets(); List <string> profiles = new List <string>(); foreach (StreamTarget target in targets) { profiles = profiles.Concat(GetStreamControl(type).GetTranscoderProfilesForTarget(target.Name).Select(x => x.Name)).ToList(); } // get view properties VideoPlayer player = targets.First(x => x.Name == profile.Target).Player; string viewName = Enum.GetName(typeof(VideoPlayer), player) + "Player"; // player size WebResolution playerSize; if (!video) { playerSize = new WebResolution() { Width = 300, Height = 150 }; } else { playerSize = GetStreamControl(type).GetStreamSize(type, GetProvider(type), itemId, profile.Name); } // generate url RouteValueDictionary parameters = new RouteValueDictionary(); parameters["item"] = itemId; parameters["transcoder"] = profile.Name; // generate view return(PartialView(new PlayerViewModel { Transcoders = profiles, Transcoder = profile.Name, Player = player, PlayerViewName = viewName, URL = Url.Action(Enum.GetName(typeof(WebStreamMediaType), type), parameters), Size = playerSize })); }
internal static WebTranscoderProfile TranscoderProfile(KeyValuePair <string, EndPointProfile> profile) { int bandwith = 0; string mime = "video/MP2T"; int maxHeight = profile.Value?.MediaTranscoding?.VideoSettings?.MaxHeight ?? 0; int maxWidth = Convert.ToInt32((double)maxHeight * (16.0 / 9.0)); string transport = "http"; long audioBitrate = 512; long videoBitRate = 10000; if (profile.Value?.MediaTranscoding?.VideoTargets?.Count > 0) { var video = profile.Value.MediaTranscoding.VideoTargets.First(); if (video.Target.MaxVideoBitrate > 0) { videoBitRate = video.Target.MaxVideoBitrate; } if (video.Target.AudioBitrate > 0) { audioBitrate = video.Target.AudioBitrate; } if (videoBitRate > 0 && audioBitrate > 0) { bandwith = Convert.ToInt32(videoBitRate + audioBitrate); } if (video.Target.MaxVideoHeight > maxHeight) { maxHeight = video.Target.MaxVideoHeight; } if (video.Target.AspectRatio > 0) { maxWidth = Convert.ToInt32((float)maxHeight * video.Target.AspectRatio); } else { maxWidth = Convert.ToInt32((double)maxHeight * (16.0 / 9.0)); } if (video.Target.VideoContainerType == VideoContainer.Hls) { transport = "httplive"; mime = "application/x-mpegURL"; } //Impossible to guess the right MIME without knowing source. Could be a live stream or direct profile f.ex. //List<string> profiles = ProfileMime.ResolveVideoProfile(profile.Value.MediaTranscoding.Video[0].Target.VideoContainerType, profile.Value.MediaTranscoding.Video[0].Target.VideoCodecType, // profile.Value.MediaTranscoding.Video[0].Target.AudioCodecType, profile.Value.MediaTranscoding.Video[0].Target.EncodingProfileType, profile.Value.MediaTranscoding.Video[0].Target.LevelMinimum, // 0, maxWidth, maxHeight, profile.Value.MediaTranscoding.Video[0].Target.MaxVideoBitrate, profile.Value.MediaTranscoding.Video[0].Target.AudioBitrate, Transcoding.Service.Timestamp.None); //ProfileMime.FindCompatibleMime(profile.Value, profiles, ref mime); } WebTranscoderProfile webTranscoderProfile = new WebTranscoderProfile { Bandwidth = bandwith, Description = profile.Value.Name, HasVideoStream = true, MIME = mime, MaxOutputHeight = maxHeight, MaxOutputWidth = maxWidth, Name = profile.Value.Name, Targets = profile.Value.Targets, Transport = transport }; return(webTranscoderProfile); }