コード例 #1
0
ファイル: CreateLiveStream.cs プロジェクト: voddy-group/voddy
        public void PrepareLiveChat(IJobDetail chatDownloadJob, long streamId)
        {
            var        schedulerFactory = new StdSchedulerFactory(QuartzSchedulers.RamScheduler());
            IScheduler scheduler        = schedulerFactory.GetScheduler().Result;

            scheduler.Start();

            ISimpleTrigger trigger = (ISimpleTrigger)TriggerBuilder.Create()
                                     .WithIdentity("LiveStreamDownloadTrigger" + streamId)
                                     .StartNow()
                                     .Build();

            scheduler.ScheduleJob(chatDownloadJob, trigger);
        }
コード例 #2
0
        public DeleteStreamReturn DeleteSingleStreamLogic(long streamId)
        {
            using (var context = new MainDataContext()) {
                var stream = context.Streams.FirstOrDefault(item => item.streamId == streamId);
                if (stream == null)
                {
                    stream = context.Streams.FirstOrDefault(item => item.vodId == streamId); // add live stream delete capabilities
                }

                if (stream != null)
                {
                    if (stream.downloadJobId != null)
                    {
                        var splitJobKey = stream.downloadJobId.Split(".");
                        try {
                            JobHelpers.CancelJob(splitJobKey[1], splitJobKey[0], QuartzSchedulers.PrimaryScheduler(), true);
                        } catch (MissingJobException e) {
                            _logger.Info(e.Message);
                        }
                    }

                    if (stream.vodId != 0)
                    {
                        try {
                            CleanUpStreamFiles(GlobalConfig.GetGlobalConfig("contentRootPath"), stream.vodId, stream.streamerId);
                        } catch (DirectoryNotFoundException) {
                            CleanUpStreamFiles(GlobalConfig.GetGlobalConfig("contentRootPath"), stream.streamId, stream.streamerId);
                        }
                    }
                    else
                    {
                        CleanUpStreamFiles(GlobalConfig.GetGlobalConfig("contentRootPath"), stream.streamId, stream.streamerId);
                    }

                    context.Remove(stream);

                    if (stream.chatDownloadJobId != null)
                    {
                        var splitJobKey = stream.chatDownloadJobId.Split(".");
                        try {
                            JobHelpers.CancelJob(splitJobKey[1], splitJobKey[0], QuartzSchedulers.PrimaryScheduler(), true);
                        } catch (MissingJobException e) {
                            _logger.Info(e.Message);
                        }
                    }

                    using (var chatContext = new ChatDataContext()) {
                        chatContext.Chats.RemoveRange(chatContext.Chats.Where(item => item.streamId == streamId));
                        chatContext.SaveChanges();
                    }
                }

                context.SaveChanges();
            }

            TwitchApiHelpers twitchApiHelpers = new TwitchApiHelpers();
            var request =
                twitchApiHelpers.TwitchRequest("https://api.twitch.tv/helix/videos?id=" + streamId, Method.GET);

            if (request.StatusCode == HttpStatusCode.OK)
            {
                return(new DeleteStreamReturn {
                    isStillAvailable = true
                });
            }

            return(new DeleteStreamReturn {
                isStillAvailable = false
            });
        }
コード例 #3
0
        public Streamer CreateStreamerLogic(Streamer body)
        {
            Streamer returnStreamer;

            using (var context = new MainDataContext()) {
                Streamer streamer = context.Streamers.FirstOrDefault(item => item.streamerId == body.streamerId);

                if (streamer == null)
                {
                    // if streamer does not exist in database and want to add
                    _logger.Info("Adding new streamer...");

                    string etag = "";
                    if (GlobalConfig.GetGlobalConfig("contentRootPath") != null)
                    {
                        CreateFolder($"{GlobalConfig.GetGlobalConfig("contentRootPath")}/streamers/{body.streamerId}/");
                        if (!string.IsNullOrEmpty(body.thumbnailLocation))
                        {
                            etag = DownloadHelpers.DownloadFile(body.thumbnailLocation,
                                                                $"{GlobalConfig.GetGlobalConfig("contentRootPath")}/streamers/{body.streamerId}/thumbnail.png");
                        }
                    }


                    streamer = new Streamer {
                        streamerId        = body.streamerId,
                        displayName       = body.displayName,
                        username          = body.username,
                        isLive            = body.isLive ?? false,
                        quality           = body.quality == "{\"resolution\":0,\"fps\":0}" ? null : body.quality,
                        getLive           = body.getLive ?? false,
                        thumbnailLocation = $"streamers/{body.streamerId}/thumbnail.png",
                        thumbnailETag     = etag
                    };

                    context.Streamers.Add(streamer);
                    returnStreamer = streamer;
                } /*else if (streamer != null) {
                   * // if streamer exists then update
                   * Console.WriteLine("Updating streamer...");
                   * streamer.streamerId = body.streamerId;
                   * streamer.displayName = body.displayName;
                   * streamer.username = body.username;
                   * streamer.description = body.description;
                   * streamer.viewCount = body.viewCount;
                   * streamer.thumbnailLocation = $"streamers/{body.streamerId}/thumbnail.png";
                   * returnStreamer = streamer;
                   *
                   * IList<Parameter> headers = downloadHelpers.GetHeaders(body.thumbnailLocation);
                   * for (var x = 0; x < headers.Count; x++) {
                   *    if (headers[x].Name == "ETag") {
                   *        var etag = headers[x].Value;
                   *        if (etag != null) {
                   *            if (streamer.thumbnailETag != etag.ToString().Replace("\"", "")) {
                   *                if (contentRootPath != null)
                   *                    Console.WriteLine("Detected new thumbnail image, downloading...");
                   *                streamer.thumbnailETag = downloadHelpers.DownloadFile(body.thumbnailLocation,
                   *                    $"{contentRootPath.value}/streamers/{body.streamerId}/thumbnail.png");
                   *            }
                   *        }
                   *    }
                   * }
                   * }*/
                else
                {
                    //something strange has happened
                    returnStreamer = new Streamer();
                }

                //if (isNew) {
                //StartupJobs startupJobs = new StartupJobs();
                List <Streamer> streamers = new List <Streamer> {
                    streamer
                };                                                        //lazy
                JobHelpers.NormalJob <CheckForStreamerLiveStatusJob>("CreateStreamerUpdateLiveStatusJob", "CreateStreamerUpdateLiveStatusTrigger", QuartzSchedulers.PrimaryScheduler());
                IJobDetail job = JobBuilder.Create <UpdateStreamerDetailsJob>()
                                 .WithIdentity("UpdateStreamerDetailsJob")
                                 .Build();

                job.JobDataMap.Put("listOfStreamers", streamers);

                var        schedulerFactory = new StdSchedulerFactory(QuartzSchedulers.PrimaryScheduler());
                IScheduler scheduler        = schedulerFactory.GetScheduler().Result;
                scheduler.Start();

                ISimpleTrigger trigger = (ISimpleTrigger)TriggerBuilder.Create()
                                         .WithIdentity("UpdateStreamerDetailsTrigger")
                                         .StartNow()
                                         .Build();

                scheduler.ScheduleJob(job, trigger);
                //}

                context.SaveChanges();
            }

            return(returnStreamer);
        }
コード例 #4
0
ファイル: StreamHelpers.cs プロジェクト: voddy-group/voddy
        public static void SetDownloadToFinished(long streamId, bool isLive)
        {
            Logger _logger = new NLog.LogFactory().GetCurrentClassLogger();

            using (var context = new MainDataContext()) {
                Stream dbStream;

                dbStream = context.Streams.FirstOrDefault(item => item.streamId == streamId);

                string streamFile = GlobalConfig.GetGlobalConfig("contentRootPath") + dbStream.location + dbStream.fileName;
                dbStream.size        = new FileInfo(streamFile).Length;
                dbStream.downloading = false;

                NotificationHub.Current.Clients.All.SendAsync($"{streamId}-completed",
                                                              dbStream);

                if (isLive)
                {
                    _logger.Info("Stopping live chat download...");
                    if (dbStream.chatDownloadJobId.Contains("."))
                    {
                        var splitJobKey = dbStream.chatDownloadJobId.Split(".");
                        JobHelpers.CancelJob(splitJobKey[1], splitJobKey[0], QuartzSchedulers.PrimaryScheduler());
                    }
                    else
                    {
                        JobHelpers.CancelJob(dbStream.chatDownloadJobId, null,
                                             QuartzSchedulers.PrimaryScheduler());
                    }

                    dbStream.chatDownloading = false;
                    dbStream.duration        = getStreamDuration(streamFile);
                    GenerateThumbnailDuration(streamId);
                }
                else
                {
                    _logger.Info("Stopping VOD chat download.");
                }

                context.SaveChanges();

                // make another background job for this
                string checkVideoThumbnailsEnabled = GlobalConfig.GetGlobalConfig("generateVideoThumbnails");

                if (checkVideoThumbnailsEnabled != null && checkVideoThumbnailsEnabled == "True")
                {
                    _logger.Info("Queueing video thumbnail creation job...");
                    IJobDetail job = JobBuilder.Create <GenerateVideoThumbnailJob>()
                                     .WithIdentity("GenerateVideoThumbnail" + streamId)
                                     .UsingJobData("streamId", streamId)
                                     .UsingJobData("streamFile", streamFile)
                                     .Build();

                    var        schedulerFactory = new StdSchedulerFactory(QuartzSchedulers.PrimaryScheduler());
                    IScheduler scheduler        = schedulerFactory.GetScheduler().Result;
                    scheduler.Start();

                    ISimpleTrigger trigger = (ISimpleTrigger)TriggerBuilder.Create()
                                             .WithIdentity("GenerateVideoThumbnail" + streamId)
                                             .StartNow()
                                             .Build();

                    scheduler.ScheduleJob(job, trigger);
                    //BackgroundJob.Enqueue(() => GenerateVideoThumbnail(streamId, streamFile));
                }
            }
        }
コード例 #5
0
        public bool PrepareDownload(StreamExtended stream)
        {
            string streamUrl;

            streamUrl = "https://www.twitch.tv/videos/" + stream.streamId;

            YoutubeDlVideoJson.YoutubeDlVideoInfo youtubeDlVideoInfo =
                StreamHelpers.GetDownloadQualityUrl(streamUrl, stream.streamerId);

            string streamDirectory = $"{GlobalConfig.GetGlobalConfig("contentRootPath")}streamers/{stream.streamerId}/vods/{stream.streamId}";


            Directory.CreateDirectory(streamDirectory);

            if (!string.IsNullOrEmpty(stream.thumbnailLocation))
            {
                //todo handle missing thumbnail, maybe use youtubedl generated thumbnail instead
                DownloadHelpers.DownloadFile(
                    stream.thumbnailLocation.Replace("%{width}", "320").Replace("%{height}", "180"),
                    $"{streamDirectory}/thumbnail.jpg");
            }

            string title      = String.IsNullOrEmpty(stream.title) ? "vod" : stream.title;
            string outputPath = $"{streamDirectory}/{title}.{stream.streamId}";

            string dbOutputPath = $"streamers/{stream.streamerId}/vods/{stream.streamId}/{title}.{stream.streamId}.mp4";

            //TODO more should be queued, not done immediately


            IJobDetail job;
            string     triggerIdentity;

            job = JobBuilder.Create <DownloadStreamJob>()
                  .WithIdentity("StreamDownload" + stream.streamId)
                  .UsingJobData("title", title)
                  .UsingJobData("streamDirectory", streamDirectory)
                  .UsingJobData("formatId", youtubeDlVideoInfo.formatId)
                  .UsingJobData("url", streamUrl)
                  .UsingJobData("isLive", false)
                  .UsingJobData("youtubeDlVideoInfoDuration", youtubeDlVideoInfo.duration)
                  .UsingJobData("retry", true)
                  .RequestRecovery()
                  .Build();

            job.JobDataMap.Put("stream", stream);
            triggerIdentity = $"StreamDownload{stream.streamId}";


            /*string jobId = BackgroundJob.Enqueue(() =>
             *  DownloadStream(stream, title, streamDirectory, youtubeDlVideoInfo.url, CancellationToken.None,
             *      isLive, youtubeDlVideoInfo.duration));*/

            Stream?    dbStream;
            bool       downloadChat    = false;
            IJobDetail chatDownloadJob = new JobDetailImpl();

            using (var context = new MainDataContext()) {
                dbStream = context.Streams.FirstOrDefault(item => item.streamId == stream.streamId);

                if (dbStream != null)
                {
                    dbStream.streamId = stream.streamId;

                    dbStream.streamerId    = stream.streamerId;
                    dbStream.quality       = youtubeDlVideoInfo.quality;
                    dbStream.url           = youtubeDlVideoInfo.url;
                    dbStream.title         = stream.title;
                    dbStream.createdAt     = stream.createdAt;
                    dbStream.location      = $"streamers/{stream.streamerId}/vods/{stream.streamId}/";
                    dbStream.fileName      = $"{title}.{stream.streamId}.mp4";
                    dbStream.duration      = youtubeDlVideoInfo.duration;
                    dbStream.downloading   = true;
                    dbStream.downloadJobId = job.Key.ToString();
                }
                else
                {
                    downloadChat    = true;
                    chatDownloadJob = JobBuilder.Create <ChatDownloadJob>()
                                      .WithIdentity("DownloadChat" + stream.streamId)
                                      .UsingJobData("streamId", stream.streamId)
                                      .UsingJobData("retry", true)
                                      .RequestRecovery()
                                      .Build();

                    dbStream = new Stream {
                        streamId          = stream.streamId,
                        streamerId        = stream.streamerId,
                        quality           = youtubeDlVideoInfo.quality,
                        title             = stream.title,
                        url               = youtubeDlVideoInfo.url,
                        createdAt         = stream.createdAt,
                        location          = $"streamers/{stream.streamerId}/vods/{stream.streamId}/",
                        fileName          = $"{title}.{stream.streamId}.mp4",
                        duration          = youtubeDlVideoInfo.duration,
                        downloading       = true,
                        chatDownloading   = true,
                        downloadJobId     = job.Key.ToString(),
                        chatDownloadJobId = chatDownloadJob.Key.ToString()
                    };
                    // only download chat if this is a new vod


                    context.Add(dbStream);
                }

                context.SaveChanges();
            }

            //var chatSchedulerFactory = new StdSchedulerFactory(QuartzSchedulers.SingleThreadScheduler());
            var vodSchedulerFactory = new StdSchedulerFactory(QuartzSchedulers.PrimaryScheduler());
            //IScheduler chatScheduler = chatSchedulerFactory.GetScheduler().Result;
            IScheduler vodScheduler = vodSchedulerFactory.GetScheduler().Result;

            //chatScheduler.Start();
            vodScheduler.Start();

            ISimpleTrigger trigger = (ISimpleTrigger)TriggerBuilder.Create()
                                     .WithIdentity(triggerIdentity)
                                     .StartNow()
                                     .Build();

            vodScheduler.ScheduleJob(job, trigger);

            if (downloadChat)
            {
                ISimpleTrigger chatDownloadTrigger = (ISimpleTrigger)TriggerBuilder.Create()
                                                     .WithIdentity("DownloadChat" + stream.streamId)
                                                     .StartNow()
                                                     .Build();

                vodScheduler.ScheduleJob(chatDownloadJob, chatDownloadTrigger);
            }

            //_hubContext.Clients.All.SendAsync("ReceiveMessage", CheckForDownloadingStreams());

            return(true);
        }
コード例 #6
0
ファイル: CreateLiveStream.cs プロジェクト: voddy-group/voddy
        public Task PrepareLiveStreamDownload(StreamExtended stream, string streamerName)
        {
            streamUrl = "https://twitch.tv/" + streamerName;

            YoutubeDlVideoJson.YoutubeDlVideoInfo youtubeDlVideoInfo = StreamHelpers.GetDownloadQualityUrl(streamUrl, stream.streamerId);
            streamDirectory = $"{GlobalConfig.GetGlobalConfig("contentRootPath")}streamers/{stream.streamerId}/vods/{stream.streamId}";

            try {
                Directory.CreateDirectory(streamDirectory);
            } catch (UnauthorizedAccessException e) {
                _logger.Error(e);
                // todo handle this
                throw;
            }

            outputPath = $"{streamDirectory}/{stream.title}.{stream.streamId}";

            dbOutputPath = $"streamers/{stream.streamerId}/vods/{stream.streamId}/{stream.title}.{stream.streamId}.mp4";

            var job = JobBuilder.Create <LiveStreamDownloadJob>()
                      .WithIdentity("LiveStreamDownloadJob" + stream.streamId)
                      .UsingJobData("url", streamUrl)
                      .UsingJobData("streamDirectory", streamDirectory)
                      .UsingJobData("streamId", stream.streamId)
                      .UsingJobData("title", stream.title)
                      .UsingJobData("streamerId", stream.streamerId)
                      .Build();

            var triggerIdentity = $"LiveStreamDownload{stream.streamId}";

            var chatDownloadJob = JobBuilder.Create <LiveStreamChatDownloadJob>()
                                  .WithIdentity("LiveStreamChatDownloadJob" + stream.streamId)
                                  .UsingJobData("channel", streamerName)
                                  .UsingJobData("streamId", stream.streamId)
                                  .Build();

            using (var context = new MainDataContext()) {
                var dbStream = new Stream {
                    streamId          = stream.streamId,
                    vodId             = stream.vodId,
                    streamerId        = stream.streamerId,
                    quality           = youtubeDlVideoInfo.quality,
                    title             = stream.title,
                    url               = youtubeDlVideoInfo.url,
                    createdAt         = stream.createdAt,
                    location          = $"streamers/{stream.streamerId}/vods/{stream.streamId}/",
                    fileName          = $"{stream.title}.{stream.streamId}.mp4",
                    downloading       = true,
                    chatDownloading   = true,
                    downloadJobId     = job.Key.ToString(),
                    chatDownloadJobId = chatDownloadJob.Key.ToString()
                };

                context.Add(dbStream);
                context.SaveChanges();
            }

            var        schedulerFactory = new StdSchedulerFactory(QuartzSchedulers.RamScheduler());
            IScheduler scheduler        = schedulerFactory.GetScheduler().Result;

            scheduler.Start();

            ISimpleTrigger trigger = (ISimpleTrigger)TriggerBuilder.Create()
                                     .WithIdentity(triggerIdentity)
                                     .StartNow()
                                     .Build();

            scheduler.ScheduleJob(job, trigger);

            PrepareLiveChat(chatDownloadJob, stream.streamId);
            return(Task.CompletedTask);
        }