private void RefreshCheckBoxes(string language)
        {
            _netflixQualityController = new NetflixQualityController {
                Language = language, VideoFileName = _videoFileName
            };

            checkBoxNoItalics.Checked = !_netflixQualityController.AllowItalics;
            checkBoxNoItalics.Enabled = !_netflixQualityController.AllowItalics;

            var sceneChangesExists = false;

            if (_netflixQualityController.VideoExists)
            {
                if (SceneChangeHelper.FromDisk(_videoFileName).Count > 0)
                {
                    sceneChangesExists = true;
                }
            }
            checkBoxSceneChange.Checked = _netflixQualityController.VideoExists && sceneChangesExists;
            checkBoxSceneChange.Enabled = _netflixQualityController.VideoExists && sceneChangesExists;

            var checkFrameRate = _subtitleFormat.GetType() == new NetflixTimedText().GetType();

            checkBoxTtmlFrameRate.Checked = checkFrameRate;
            checkBoxTtmlFrameRate.Enabled = checkFrameRate;

            checkBoxDialogHypenNoSpace.Text = !_netflixQualityController.DualSpeakersHasHyphenAndNoSpace ? "Dual Speakers: Use a hyphen with a space" : "Dual Speakers: Use a hyphen without a space";

            checkBox17CharsPerSecond.Text = string.Format(LanguageSettings.Current.NetflixQualityCheck.MaximumXCharsPerSecond, _netflixQualityController.CharactersPerSecond);
            checkBoxMaxLineLength.Text    = string.Format(LanguageSettings.Current.NetflixQualityCheck.MaximumLineLength, _netflixQualityController.SingleLineMaxLength);
        }
        private void GenerateSceneChanges(string videoFileName)
        {
            var sceneChangesGenerator = new SceneChangesGenerator();
            var threshold             = 0.4m;

            if (decimal.TryParse(Configuration.Settings.General.FFmpegSceneThreshold, NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture, out var d))
            {
                threshold = d;
            }
            using (var process = sceneChangesGenerator.GetProcess(videoFileName, threshold))
            {
                while (!process.HasExited)
                {
                    Application.DoEvents();
                    System.Threading.Thread.Sleep(100);
                    if (_abort)
                    {
                        DialogResult = DialogResult.Cancel;
                        process.Kill();
                        return;
                    }
                }
            }
            var seconds = SceneChangesGenerator.GetSeconds(sceneChangesGenerator.GetTimeCodesString().SplitToLines().ToArray());

            if (seconds.Count > 0)
            {
                SceneChangeHelper.SaveSceneChanges(videoFileName, seconds);
            }
        }
Exemple #3
0
        private void RefreshCheckBoxes(string language)
        {
            _netflixQualityController = new NetflixQualityController {
                Language = language, VideoFileName = _videoFileName, FrameRate = _frameRate
            };

            checkBoxNoItalics.Checked = !_netflixQualityController.AllowItalics;
            checkBoxNoItalics.Enabled = !_netflixQualityController.AllowItalics;

            int halfSecGapInFrames = (int)Math.Round(_frameRate / 2);

            checkBoxGapBridge.Text = $"Frame gap: 3 to {halfSecGapInFrames - 1} frames => 2 frames";

            var sceneChangesExist = false;

            if (_netflixQualityController.VideoExists)
            {
                if (SceneChangeHelper.FromDisk(_videoFileName).Count > 0)
                {
                    sceneChangesExist = true;
                }
            }
            checkBoxSceneChange.Checked = sceneChangesExist;
            checkBoxSceneChange.Enabled = sceneChangesExist;

            var checkFrameRate = _subtitleFormat.GetType() == new NetflixTimedText().GetType();

            checkBoxTtmlFrameRate.Checked = checkFrameRate;
            checkBoxTtmlFrameRate.Enabled = checkFrameRate;

            var speakerStyle             = _netflixQualityController.SpeakerStyle;
            var checkBoxSpeakerStyleText = "Dual Speakers: Use a hyphen without a space";

            if (speakerStyle == DialogType.DashBothLinesWithSpace)
            {
                checkBoxSpeakerStyleText = "Dual Speakers: Use a hyphen with a space";
            }
            else if (speakerStyle == DialogType.DashSecondLineWithSpace)
            {
                checkBoxSpeakerStyleText = "Dual Speakers: Use a hyphen with a space to denote the second speaker only";
            }
            else if (speakerStyle == DialogType.DashSecondLineWithoutSpace)
            {
                checkBoxSpeakerStyleText = "Dual Speakers: Use a hyphen without a space to denote the second speaker only";
            }

            checkBoxSpeakerStyle.Text = checkBoxSpeakerStyleText;

            checkBox17CharsPerSecond.Text = string.Format(LanguageSettings.Current.NetflixQualityCheck.MaximumXCharsPerSecond, _netflixQualityController.CharactersPerSecond);
            checkBoxMaxLineLength.Text    = string.Format(LanguageSettings.Current.NetflixQualityCheck.MaximumLineLength, _netflixQualityController.SingleLineMaxLength);
        }
        /// <summary>
        /// Check the newly-updated timing to Shot Changes rules.
        /// https://partnerhelp.netflixstudios.com/hc/en-us/articles/360051554394-Timed-Text-Style-Guide-Subtitle-Timing-Guidelines
        /// </summary>
        public void Check(Subtitle subtitle, NetflixQualityController controller)
        {
            if (!controller.VideoExists)
            {
                return;
            }

            var SceneChanges = SceneChangeHelper.FromDisk(controller.VideoFileName);

            if (SceneChanges == null || SceneChanges.Count == 0)
            {
                return;
            }

            const int twelveFramesGap = 12;
            double    twoFramesGap    = 1000.0 / controller.FrameRate * 2.0;

            foreach (Paragraph p in subtitle.Paragraphs)
            {
                var    fixedParagraph = new Paragraph(p, false);
                string comment        = string.Empty;

                List <double> previousStartSceneChanges = SceneChanges.Where(x => SubtitleFormat.MillisecondsToFrames(x * 1000) < SubtitleFormat.MillisecondsToFrames(p.StartTime.TotalMilliseconds)).ToList();
                List <double> nextStartSceneChanges     = SceneChanges.Where(x => SubtitleFormat.MillisecondsToFrames(x * 1000) > SubtitleFormat.MillisecondsToFrames(p.StartTime.TotalMilliseconds)).ToList();
                List <double> previousEndSceneChanges   = SceneChanges.Where(x => SubtitleFormat.MillisecondsToFrames(x * 1000) < SubtitleFormat.MillisecondsToFrames(p.EndTime.TotalMilliseconds)).ToList();
                List <double> nextEndSceneChanges       = SceneChanges.Where(x => SubtitleFormat.MillisecondsToFrames(x * 1000) > SubtitleFormat.MillisecondsToFrames(p.EndTime.TotalMilliseconds)).ToList();
                var           onSceneChange             = SceneChanges.Where(x => SubtitleFormat.MillisecondsToFrames(x * 1000) == SubtitleFormat.MillisecondsToFrames(p.EndTime.TotalMilliseconds)).FirstOrDefault();

                if (previousStartSceneChanges.Count > 0)
                {
                    double nearestStartPrevSceneChange = previousStartSceneChanges.Aggregate((x, y) => Math.Abs(x - p.StartTime.TotalSeconds) < Math.Abs(y - p.StartTime.TotalSeconds) ? x : y);
                    if (SubtitleFormat.MillisecondsToFrames(p.StartTime.TotalMilliseconds - nearestStartPrevSceneChange * 1000) < twelveFramesGap)
                    {
                        fixedParagraph.StartTime.TotalMilliseconds = nearestStartPrevSceneChange * 1000;
                        comment = "The in-cue is within 12 frames after the shot change";
                        controller.AddRecord(p, fixedParagraph, comment);
                    }
                }

                if (nextStartSceneChanges.Count > 0)
                {
                    double nearestStartNextSceneChange = nextStartSceneChanges.Aggregate((x, y) => Math.Abs(x - p.StartTime.TotalSeconds) < Math.Abs(y - p.StartTime.TotalSeconds) ? x : y);
                    if (SubtitleFormat.MillisecondsToFrames(nearestStartNextSceneChange * 1000 - p.StartTime.TotalMilliseconds) < twelveFramesGap)
                    {
                        fixedParagraph.StartTime.TotalMilliseconds = nearestStartNextSceneChange * 1000;
                        comment = "The in-cue is within 12 frames before the shot change";
                        controller.AddRecord(p, fixedParagraph, comment);
                    }
                }

                if (previousEndSceneChanges.Count > 0)
                {
                    double nearestEndPrevSceneChange = previousEndSceneChanges.Aggregate((x, y) => Math.Abs(x - p.EndTime.TotalSeconds) < Math.Abs(y - p.EndTime.TotalSeconds) ? x : y);
                    if (SubtitleFormat.MillisecondsToFrames(p.EndTime.TotalMilliseconds - nearestEndPrevSceneChange * 1000) < twelveFramesGap)
                    {
                        fixedParagraph.EndTime.TotalMilliseconds = nearestEndPrevSceneChange * 1000 - twoFramesGap;
                        comment = "The out-cue is within 12 frames after the shot change";
                        controller.AddRecord(p, fixedParagraph, comment);
                    }
                }

                if (nextEndSceneChanges.Count > 0)
                {
                    double nearestEndNextSceneChange = nextEndSceneChanges.Aggregate((x, y) => Math.Abs(x - p.EndTime.TotalSeconds) < Math.Abs(y - p.EndTime.TotalSeconds) ? x : y);
                    if (SubtitleFormat.MillisecondsToFrames(nearestEndNextSceneChange * 1000 - p.EndTime.TotalMilliseconds) - 1 < twelveFramesGap &&
                        SubtitleFormat.MillisecondsToFrames(p.EndTime.TotalMilliseconds) != SubtitleFormat.MillisecondsToFrames(nearestEndNextSceneChange * 1000 - twoFramesGap))
                    {
                        fixedParagraph.EndTime.TotalMilliseconds = nearestEndNextSceneChange * 1000 - twoFramesGap;
                        comment = "The out-cue is within 12 frames of the last frame before the shot change";
                        controller.AddRecord(p, fixedParagraph, comment);
                    }
                }

                if (onSceneChange > 0)
                {
                    fixedParagraph.EndTime.TotalMilliseconds = onSceneChange * 1000 - twoFramesGap;
                    comment = "The out-cue is on the shot change (respect the two-frame gap)";
                    controller.AddRecord(p, fixedParagraph, comment);
                }
            }
        }
        public void Check(Subtitle subtitle, NetflixQualityController controller)
        {
            if (!controller.VideoExists)
            {
                return;
            }

            var SceneChanges = SceneChangeHelper.FromDisk(controller.VideoFileName);

            if (SceneChanges == null || SceneChanges.Count == 0)
            {
                return;
            }

            int    halfSecGapInFrames = (int)Math.Round(controller.FrameRate / 2);
            double twoFramesGap       = 1000.0 / controller.FrameRate * 2.0;

            foreach (Paragraph p in subtitle.Paragraphs)
            {
                var    fixedParagraph = new Paragraph(p, false);
                string comment        = string.Empty;

                List <double> previousStartSceneChanges = SceneChanges.Where(x => SubtitleFormat.MillisecondsToFrames(x * 1000) < SubtitleFormat.MillisecondsToFrames(p.StartTime.TotalMilliseconds)).ToList();
                List <double> nextStartSceneChanges     = SceneChanges.Where(x => SubtitleFormat.MillisecondsToFrames(x * 1000) > SubtitleFormat.MillisecondsToFrames(p.StartTime.TotalMilliseconds)).ToList();
                List <double> previousEndSceneChanges   = SceneChanges.Where(x => SubtitleFormat.MillisecondsToFrames(x * 1000) < SubtitleFormat.MillisecondsToFrames(p.EndTime.TotalMilliseconds)).ToList();
                List <double> nextEndSceneChanges       = SceneChanges.Where(x => SubtitleFormat.MillisecondsToFrames(x * 1000) > SubtitleFormat.MillisecondsToFrames(p.EndTime.TotalMilliseconds)).ToList();
                var           onSceneChange             = SceneChanges.Where(x => SubtitleFormat.MillisecondsToFrames(x * 1000) == SubtitleFormat.MillisecondsToFrames(p.EndTime.TotalMilliseconds)).FirstOrDefault();

                if (previousStartSceneChanges.Count > 0)
                {
                    double nearestStartPrevSceneChange = previousStartSceneChanges.Aggregate((x, y) => Math.Abs(x - p.StartTime.TotalSeconds) < Math.Abs(y - p.StartTime.TotalSeconds) ? x : y);
                    if (SubtitleFormat.MillisecondsToFrames(p.StartTime.TotalMilliseconds - nearestStartPrevSceneChange * 1000) < halfSecGapInFrames)
                    {
                        fixedParagraph.StartTime.TotalMilliseconds = nearestStartPrevSceneChange * 1000;
                        comment = $"The in-cue is within {halfSecGapInFrames} frames after the shot change, snap the in-cue to the shot-change";
                        controller.AddRecord(p, fixedParagraph, comment);
                    }
                }

                if (nextStartSceneChanges.Count > 0)
                {
                    double nearestStartNextSceneChange = nextStartSceneChanges.Aggregate((x, y) => Math.Abs(x - p.StartTime.TotalSeconds) < Math.Abs(y - p.StartTime.TotalSeconds) ? x : y);
                    var    gapToSceneChange            = SubtitleFormat.MillisecondsToFrames(nearestStartNextSceneChange * 1000 - p.StartTime.TotalMilliseconds);
                    var    threshold = (int)Math.Round(halfSecGapInFrames * 0.75);
                    if (gapToSceneChange < halfSecGapInFrames)
                    {
                        if (gapToSceneChange < threshold)
                        {
                            fixedParagraph.StartTime.TotalMilliseconds = nearestStartNextSceneChange * 1000;
                            comment = $"The in-cue is 1-{threshold - 1} frames before the shot change, snap the in-cue to the shot change";
                        }
                        else
                        {
                            fixedParagraph.StartTime.TotalMilliseconds = nearestStartNextSceneChange * 1000 - (1000.0 / controller.FrameRate * halfSecGapInFrames);
                            comment = $"The in-cue is {threshold}-{halfSecGapInFrames - 1} frames before the shot change, pull the in-cue to half a second ({halfSecGapInFrames} frames) before the shot-change";
                        }

                        controller.AddRecord(p, fixedParagraph, comment);
                    }
                }

                if (previousEndSceneChanges.Count > 0)
                {
                    double nearestEndPrevSceneChange = previousEndSceneChanges.Aggregate((x, y) => Math.Abs(x - p.EndTime.TotalSeconds) < Math.Abs(y - p.EndTime.TotalSeconds) ? x : y);
                    if (SubtitleFormat.MillisecondsToFrames(p.EndTime.TotalMilliseconds - nearestEndPrevSceneChange * 1000) < halfSecGapInFrames)
                    {
                        fixedParagraph.EndTime.TotalMilliseconds = nearestEndPrevSceneChange * 1000 - twoFramesGap;
                        comment = $"The out-cue is within {halfSecGapInFrames} frames after the shot change";
                        controller.AddRecord(p, fixedParagraph, comment);
                    }
                }

                if (nextEndSceneChanges.Count > 0)
                {
                    double nearestEndNextSceneChange = nextEndSceneChanges.Aggregate((x, y) => Math.Abs(x - p.EndTime.TotalSeconds) < Math.Abs(y - p.EndTime.TotalSeconds) ? x : y);
                    if (SubtitleFormat.MillisecondsToFrames(nearestEndNextSceneChange * 1000 - p.EndTime.TotalMilliseconds) - 1 < halfSecGapInFrames &&
                        SubtitleFormat.MillisecondsToFrames(p.EndTime.TotalMilliseconds) != SubtitleFormat.MillisecondsToFrames(nearestEndNextSceneChange * 1000 - twoFramesGap))
                    {
                        fixedParagraph.EndTime.TotalMilliseconds = nearestEndNextSceneChange * 1000 - twoFramesGap;
                        comment = $"The out-cue is within {halfSecGapInFrames} frames of the last frame before the shot change";
                        controller.AddRecord(p, fixedParagraph, comment);
                    }
                }

                if (onSceneChange > 0)
                {
                    fixedParagraph.EndTime.TotalMilliseconds = onSceneChange * 1000 - twoFramesGap;
                    comment = "The out-cue is on the shot change, respect the two-frame gap";
                    controller.AddRecord(p, fixedParagraph, comment);
                }
            }
        }
Exemple #6
0
 protected override void Run(Session session, M2C_StartSceneChange message)
 {
     SceneChangeHelper.SceneChangeTo(session.ZoneScene(), message.SceneName, message.SceneInstanceId).Coroutine();
 }
 protected override async ETTask Run(Session session, M2C_StartSceneChange message)
 {
     await SceneChangeHelper.SceneChangeTo(session.ZoneScene(), message.SceneName, message.SceneInstanceId);
 }