Laden...

TimeCode (TC) Struct für Videobearbeitung

Erstellt von jaensen vor 11 Jahren Letzter Beitrag vor 10 Jahren 6.614 Views
jaensen Themenstarter:in
2.760 Beiträge seit 2006
vor 11 Jahren
TimeCode (TC) Struct für Videobearbeitung

Beschreibung:

Eine C# Implementierung des Timecode welcher bei der Videobearbeitung verwendet wird.

Methoden:

  • ToString: Gibt den Timecode im Format HH:MM:SS:FF aus
  • FromMilliseconds: Erstellt eine Timecode Instanz aus der Anzahl der Millisekunden und den FPS
  • FromTimeSpan: Erstellt eine Timecode Instanz aus einem Timespan objekt und den FPS
  • CalculateDuration: Berechnet die Dauer aus TcIn und TcOut
  • Parse: Erstellt eine MediaTimeCode Instanz aus einem String im Format HH:MM:SS:FF

public struct MediaTimeCode {

        public int Hours { get; set; }
        public int Minutes { get; set; }
        public int Seconds { get; set; }
        public int Frames { get; set; }

        public static MediaTimeCode FromMilliseconds(long milliseconds, int framesPerSecond) {

            TimeSpan timespan = TimeSpan.FromMilliseconds(milliseconds);

            return FromTimeSpan(timespan, framesPerSecond);
        }

        public static MediaTimeCode FromTimeSpan(TimeSpan timespan, int framesPerSecond) {

            double framesPerMillisecond = (double)framesPerSecond / (double)1000;
            int frames = (int)(timespan.Milliseconds * framesPerMillisecond);

            return new MediaTimeCode() {
                Hours = timespan.Hours,
                Minutes = timespan.Minutes,
                Seconds = timespan.Seconds,
                Frames = frames
            };
        }

        public static MediaTimeCode CalculateDuration(MediaTimeCode tcIn, MediaTimeCode tcOut, int fps) {

            double fpm = 60 * fps;
            double fph = 60 * fpm;

            double frameHours = tcIn.Hours * fph;
            double frameMinutes = tcIn.Minutes * fpm;
            double frameSeconds = tcIn.Seconds * fps;

            double tcInFrames = frameHours + frameMinutes + frameSeconds + tcIn.Frames;

            frameHours = tcOut.Hours * fph;
            frameMinutes = tcOut.Minutes * fpm;
            frameSeconds = tcOut.Seconds * fps;

            double tcOutFrames = frameHours + frameMinutes + frameSeconds + tcOut.Frames;

            double durationInFrames = tcOutFrames - tcInFrames;

            int fRest = (int)durationInFrames % (int)fps;
            int frames = (int)durationInFrames - fRest;

            int s = frames / (int)fps;
            int sRest = s % 60;
            int minutes = ((s - sRest) / 60) % 60;
            int hours = (100 - minutes) / 60;

            return new MediaTimeCode() {
                Hours = hours,
                Minutes = minutes,
                Seconds = sRest,
                Frames = fRest
            };
        }

        public override string ToString() {
            return string.Format("{0:00}:{1:00}:{2:00}:{3:00}",
                Hours,
                Minutes,
                Seconds,
                Frames);
        }

        public static MediaTimeCode Parse(string tcString) {

            string[] tcParts = tcString.Split(':');

            int hours = int.Parse(tcParts[0]);
            int minutes = int.Parse(tcParts[1]);
            int seconds = int.Parse(tcParts[2]);
            int frames = int.Parse(tcParts[3]);

            return new MediaTimeCode() {
                Hours = hours,
                Minutes = minutes,
                Seconds = seconds,
                Frames = frames
            };
        }
    }

Schlagwörter: Video Timecode, TcIn, TcOut, Struct

T
415 Beiträge seit 2007
vor 10 Jahren

Hi jaensen,

erstmal Danke für deine Timecode Komponente. Die hat mir ein gutes Stück Arbeit abgenommen. Mir ist nur aufgefallen, dass die Duration Berechnung nicht ganz korrekt hinhaut.

Beispielsweise bei einem Input von
tcIn = 01:00:00:00
tcOut = 01:00:33:00
FrameBase = 24

Erhalte ich ein Output von 01:00:33:00
Würde aber ein Output von 00:00:33:00 erwarten

Da ich deine Berechnung nicht ganz nachvollziehen kann und sehr schnell ein Ergebnis brauchte, habe ich zu einer Quick & Dirty Lösung gegriffen.

Dazu habe ich die durationInFrames in Millisekunden umgerechnet. Bei einer FrameBase von 24 dauert ein Frame 41.666666667 ms. Also habe ich folgendes berechnet:


TimeSpan t = TimeSpan.FromMilliseconds(durationInFrames * 41.666666667);

dann habe ich einfach aus der TimeSpan wieder den TimeCode herausgezogen:


return new MediaTimeCode()
{
     Hours = t.Hours,
     Minutes = t.Minutes,
     Seconds = t.Seconds,
     Frames = (int)Math.Round(t.Milliseconds / 41.666666667, MidpointRounding.AwayFromZero)
};

Wie sauber dies nun in jedem erdenklichen Fall funktioniert, das kann ich auf die schnelle nicht sagen (Stichwort eventuelle Rundungsfehler). Die Berechnung meiner Timeline konnte ich damit aber bisher fehlerfrei umsetzen.

S
64 Beiträge seit 2008
vor 10 Jahren

Hallo,

ich denke mal, der Abschnitt


    int s = frames / (int)fps;
    int sRest = s % 60;
    int minutes = ((s - sRest) / 60) % 60;
    int hours = (100 - minutes) / 60;

in der Funktion CalculateDuration müsste eher wie folgt lauten:


    int s = frames / (int)fps;
    int sRest = s % 60;
    int minutes = (s / 60) % 60;
    int hours = s / 3600;

Grüße
Maik

A
52 Beiträge seit 2011
vor 10 Jahren

Wieso denn immer das Rad neu erfinden statt einfachd as bestehende zu erweitern:


using System;
public static class MediaTimeCode
{
    public static int TotalFrames(this TimeSpan TimeCode, int FPS)
    {
        return (int)((FPS / 1000D) * TimeCode.TotalMilliseconds);
    }

    public static int Frame(this TimeSpan TimeCode, int FPS)
    {
        return (int)((FPS / 1000D) * TimeCode.Milliseconds);
    }

    public static String ToMediaTimeCode(this TimeSpan TimeCode, int FPS)
    {
        return String.Format("{0:T}:{1}", TimeCode, TimeCode.Frame(FPS));
    }
}

das fügt dem TimeSpan struct einafch eine Frame methode hin zu und sollte ziemlich denselben effekt wie dein struct haben 😃

außerdem lässt sich so weiter mit TimeSpans arbeiten die in manchen hinsichten besser sind

Gruß Alexander Schill