Die Backtimingprozedur, die ich vor einiger Zeit öffentlich gemacht habe, funktioniert so nur für den Assist-Modus. Möchte man einen Mixdown einer gevoicetrackten Produktion erstellen, so braucht es eine etwas andere Vorgehensweise; erst recht, wenn die Ausspielung live im Automatikbetrieb erfolgen soll.
Für diese beiden Fälle ist das folgende Skript geeignet.
Was passiert also beim „Fahren auf Zeit“? Für Quereinsteiger: Ein (in der Regel instrumentaler, nicht ausgeblendeter) Schlußtitel wird zunächst stumm (ohne dessen Regler aufzuziehen) zu einer Zeit abgefahren, daß er beispielsweise genau zum Stundenende fertig ist. Um den Übergang zu kaschieren, wird der letzte Titel abmoderiert (Fachjargon: „auf die Naht sprechen“), unter der Abmoderation langsam etwas aufgeblendet (Fachjargon: „mit Musik anblasen“. Wirklich. Hab’ ich nicht erfunden!) und zum Ende der Moderation dann voll aufgeblendet. Damit endet der Schlußtitel auf den Punkt.
Das ganze passiert jetzt automatisch. Wir benötigen dazu zunächst
- eine Schaltfläche (Statischer Text), deren Name und ausgebender Befehl im Kopf des Skripts selbst festgelegt werden kann.
Damit schalten wir die Backtimingautomatik frei. Ich gehe davon aus, daß in der Playlist vor dem betreffenden Fixtimeelement (welches den Zeitpunkt für das geplante Ende definiert) zunächst als letztes Element der einzublendende Schlußtitel und als vorletztes die Abmoderation eingestellt ist. Soviel Ordnung muß sein. Das Fixtimeelement darf auch Audio enthalten und mittels Anchor
an die Fixzeit gepinnt sein.
Jetzt brauchen wir noch
- ein Steuerelement beliebigen (aber eindeutigen) Namens (kann im Skript festgelegt werden) ohne Audio (Länge
0:00
), um der Automatik zu sagen, daß tatsächlich ein Backtiming stattfinden soll. Dieses Element muß direkt vor dem Fixtimeelement eingestellt werden.
Das Skript stellt bei jedem Start eines Players zunächst fest, ob die Voraussetzungen (Abmod, Schlußtitel, Steuerelement vorhanden) gegeben sind. Falls ja, wird die Abmoderation daraufhin geprüft, ob ein Ramp 1
-Marker vorhanden ist. Dies ist der (manuell zu setzende) Zeitpunkt, an welchem die Musikblase starten soll. Ist diese Marke nicht vorhanden, so wird sie selbsttätig an den Beginn der Modulation der Abmod gesetzt.
Gleiches erfolgt entsprechend am Modulationsende, wenn kein Outro
-Marker für den Beginn der finalen Aufblende gesetzt ist.
Legt man Wert auf die automatische Bestimmung, sollte in der Konfiguration Auto-Cue aktiviert und auf vernünftige Werte (um –40 dB) gesetzt sein. (Konfiguration > Verschiedenes > Auto-Cue > Cue In automatisch bestimmen
, bzw. Cue Out …
)
Die betreffenden Elemente werden dann farblich markiert, damit es schöner ist. Anschließend werden für den Schlußtitel Startzeitpunkt und Hüllkurvenpunkte gesetzt. Die Dynamik der Musikblase (Pegel, Länge der Blenden) läßt sich im Kopf des Skripts frei definieren.
Ist die Playlist für einen Mixdown vorgesehen, so wird als harte Fixzeit die geplante Dauer der Produktion (also z. B. 00:59:55
) gesetzt.
Das Skript führt nur die Berechnung der Längen durch. Die Titel sollten zeitlich schon in die Stunde (bzw. in den betreffenden Zeitraum) passen, das ist bei einer Voicetracking-Vorproduktion in der Regel auch der Fall. Bei automatischer Playlistgenerierung muß der Betreiber respektive ein anderes Skript für die korrekte Anzahl der Elemente sorgen. Ist der verbleibende Rest des Schlußtitels nicht mindestens so lang wie die Abmoderation plus der Aufblende (d. h. es sind zuwenige oder zuviele Titel vorgesehen bzw. es stimmt die Basiszeit nicht, weil noch kein Player gestartet ist und sie nicht fortlaufend aktualisiert wird), erscheint eine Fehlermeldung.
Um einen reibungslosen Ablauf des Backtimings zu gewährleisten, sind mindestens drei Player erforderlich. Wer im Regelfall nur zwei Player definiert hat, kann, wenn das Backtiming an der kritischen Stelle ist, einen dritten Player zuschalten, der am Ende des Schlußtitels wieder weggenommen wird. Wählt man diese Option nicht, muß gewährleistet werden, daß sich der abzusagende und der Schlußtitel nicht überschneiden.
Ein kleiner Trost zum Schluß: Das alles klingt komplizierter als es tatsächlich ist. Hat man einmal den Bogen raus, funktioniert die Mimik tadellos. (Jedenfalls auf meinem System. Wahrscheinlich ist bei Euch alles ganz anders.)
Pünktliche Grüße
TSD
Ich wollte gerne das etwas längliche Skript als Anhang hochladen, aber das geht nicht, da die Endung .mls
für den Hochlad gesperrt ist. Speziell in diesem Forum halte ich das nicht eben für zielführend. Also:
{
+------------------------------------------------------------------------+
| |
| Backtiming-Skript für Playout und Mixdown |
| |
| Version 4.1, © 2019 Tondose (https://community.mairlist.com/u/tondose) |
| |
+------------------------------------------------------------------------+
Voraussetzungen:
• Schaltfläche mit beliebigem Namen (festzulegen in den Einstellungen)
als statischer Text.
• Schaltfläche gibt beliebigen Befehl (festzulegen in den Einstellungen).
• Fixtime-Element mit beliebiger harter Fixzeit, darf Audio enthalten.
Für Mixdown Fixzeit von Dauer der Vorproduktion, z.B. 00:59:59.
• Steuerelement in Playlist der Länge 0'00" und beliebig festzulegendem Namen.
• Schlußmoderation kann mit Ramp1- und Outro-Marker zur Steuerung
der Musikblase versehen werden.
Changelog:
V4.1
[*] Neuberechnung der Parameter bei jedem Playerstart
[+] Farbe der Elemente nach Reset bestimmbar
[+] Plausibilitätsprüfung für CueIn
V4.0:
[*] Code völlig umgestellt
[*] Neue Steuerung sowohl für Mixdown als auch Automatikausspielung
[+] Beliebiger Buttonname und -Befehl
[+] Fixtime-Element kann Audio enthalten
[*] Auslösung des Backtimings durch Steuerelement mit beliebig
festzulegendem Namen
[+] Automatische Cuemarken für Abmod bei Modulationsbeginn und -ende
V3.13:
[*] GetPlayerCount in procedure OnLoad verlegt
[-] Kunstpause beim Backtiming entfernt
[+] Auf Wunsch schreiende Fehlermeldungen
[+] OnUnload hinzugefügt
[+] CueIn des Schlußtitels wird beim Abschalten wiederhergestellt
[+] Hüllkurvenpunkte des Schlußtitels werden beim Abschalten gelöscht
[*] TIMINGOFFSET greift sinnvoller ein
[-] irreführenden Titel geändert
[+] Changelog etabliert
V3.12:
[*] Plausibilitätsprüfung völlig neu geschrieben
[*] Code neu strukturiert
V3.11:
[*/+/-] Das will keiner wissen
V1.0:
[*] Erste Version
}
const //Randbedingungen definieren
STARTLEVEL = -50; // Startpegel der Blase in dBr
MODLEVEL = -12; // Pegel der Blase in dBr (während Mod)
FADEINDURATION = 3; // Fade-In-Zeit in Sekunden (zur Einblendung unter Mod)
FADEUPDURATION = 2; // Fade-Up-Zeit in Sekunden (nach der Mod)
FADEUPOFFSET = 1; // Beginn der Aufblende bei AutoCue verfrühen
TIMINGOFFSET = 0; // Offset für Schlußtitel in Sekunden, negative Werte verkürzen
SET3PLAYERS = true; // Drei Player beim Backtiming verwenden
POPUPERRORS = true; // Fehlermeldungen hervorheben
BTCAPTION = 'Backtiming'; // Titel des Steuerelements in Playlist
BUTTONCMD = 'BACKTIMING'; // Befehl bei Klick auf Button
BUTTONNAME = 'BUTTON.BACKTIMING'; // Buttonname für Fernsteuerung
COLORON = '#00FF00'; // Buttonfarbe "ein"
COLOROFF = '#AAAAAA'; // Buttonfarbe "aus"
COLORALARM = '#FF0000'; // Buttonfarbe "Alarm"
TEXTON = '#000000'; // Textfarbe "ein"
TEXTOFF = '#666666'; // Textfarbe "aus"
TEXTALARM = '#FFFFFF'; // Textfarbe "Alarm"
COLORFIXITEM = $0000FF; // Farbe des Fixtime-Elementes
COLORENDTITLE = $00FF00; // Farbe des Schlußtitels
COLORENDMOD = $FF0000; // Farbe der Abmoderation
COLORRESET = $EEEEEE; // Farbe nach Reset der Elemente
{ ---------------------------------------------------------------------------- }
var // Deklaration der Variablen
PlzBacktime, BacktimeError: boolean;
PlayerCount, FixIndex: integer;
StartTime, EndTime, EndModStartTime, CueStartTime: TDateTime;
EndTitleDuration, EndTitleCue, OrgCueIn: TTimeValue;
EndMod, EndTitle, FixItem, BTItem: IPlaylistItem;
procedure OnLoad; // Initialisierung
begin
PlzBacktime := false;
BacktimeError := false;
PlayerCount := CurrentPlaylist.GetPlayerCount; // Playeranzahl feststellen
ExecuteCommand(BUTTONNAME + ' BACKGROUNDCOLOR ' + COLOROFF);
ExecuteCommand(BUTTONNAME + ' FONTCOLOR ' + TEXTOFF);
end;
procedure ButtonAlarm; // Button "Warnung"
begin
ExecuteCommand(BUTTONNAME + ' BACKGROUNDCOLOR ' + COLORALARM);
ExecuteCommand(BUTTONNAME + ' FONTCOLOR ' + TEXTALARM);
end;
procedure ButtonOn; // Button "einschalten"
begin
ExecuteCommand(BUTTONNAME + ' BACKGROUNDCOLOR ' + COLORON);
ExecuteCommand(BUTTONNAME + ' FONTCOLOR ' + TEXTON);
end;
procedure ButtonOff; // Button "ausschalten"
begin
ExecuteCommand(BUTTONNAME + ' BACKGROUNDCOLOR ' + COLOROFF);
ExecuteCommand(BUTTONNAME + ' FONTCOLOR ' + TEXTOFF);
EndTitle.SetColor(COLORRESET);
EndMod.SetColor(COLORRESET);
FixItem.SetColor(COLORRESET);
end;
procedure BTError(Message: string); // Routine für Fehlermeldung
begin
BacktimeError := true;
ButtonAlarm;
SystemLog('Backtimingfehler: ' + Message);
if POPUPERRORS then
ShowMessage(Message);
end;
procedure FindBacktimingItems; // Vorbereitungen für Backtiming
begin
if CurrentPlaylist.GetNextFixedTime > 0 then begin
FixItem := CurrentPlaylist.GetNextFixedTimeItem; // Nächstes Fixtime-Element suchen
FixIndex := CurrentPlaylist.IndexOf(FixItem); // Index feststellenm
BTItem := CurrentPlaylist.GetItem(FixIndex - 1); // Steuerelement
if (BTItem.GetTitle = BTCAPTION) AND (BTItem.GetDuration = 0) then begin // Prüfen, ob gültig
BacktimeError := false; // Wenn ja, Backtiming freigeben
end
else begin
BacktimeError := true;
end;
EndTitle := CurrentPlaylist.GetItem(FixIndex - 2); // Schlußtitel …
EndMod := CurrentPlaylist.GetItem(FixIndex - 3); // … und Abmoderation bestimmen
OrgCueIn := EndTitle.GetCuePosition(ptCueIn); // Ursprüngliches CueIn festhalten
if (EndTitle.GetDuration = 0) OR (EndMod.GetDuration = 0) then begin
BTError ('Elemente zum Backtimen müssen eine Spieldauer haben.'); // Fehler, wenn keine Spieldauer
end;
end;
end;
procedure ClearBacktiming(Title: IPlaylistItem);
begin
Title.SetCuePosition(ptCueIn, OrgCueIn); // Schlußtitel auf urspr. CueIn zurücksetzen …
Title.GetVolumeEnvelope.Clear; // … und Hüllkurvenpunkte löschen
end;
procedure Backtiming; // Backtimingprozedur
var
TempCuePosition: TTimeValue;
begin
if (FixItem.GetDuration > 0) AND (EndTitle.GetCuePosition(ptStartNext) > 0)
then EndTitleDuration := EndTitle.GetAudibleDuration
- (EndTitle.GetAudibleDuration - EndTitle.GetCuePosition(ptStartNext)) // Wenn Fixtime-Element Dauer hat, auf StartNext cuen.
else
EndTitleDuration := EndTitle.GetAudibleDuration; // Länge des Schlußtitels feststellen
EndTitle.GetVolumeEnvelope.Clear; // Sicherheitshalber Hüllkurvenpunkte löschen
EndTitle.SetColor(COLORENDTITLE); // Schön farbig machen
EndMod.SetColor(COLORENDMOD);
FixItem.SetColor(COLORFIXITEM);
EndTime := frac(CurrentPlaylist.GetMetadata(FixIndex).
GetStartTime(sttCalculated)); // Endzeit feststellen (Startzeit des Fixtime-Elementes)
EndModStartTime := CurrentPlaylist.
GetMetadata(CurrentPlaylist.IndexOf(EndMod)).GetStartTime(sttCalculated); // Startzeit der Endmod feststellen
if EndMod.GetCuePosition(ptRamp1) = 0 then begin // Feststellen, ob EndMod Ramp1-Marker besitzt, falls nicht, …
TempCuePosition := EndMod.GetCuePosition(ptCueIn); // … ursprüngliches CueIn merken, …
CurrentPlaylist.BeginRead; // … Playlist sperren, …
try
EndMod.AutoSearchPosition(ptCueIn); // … per AutoCue Modulationsbeginn feststellen, …
finally
CurrentPlaylist.EndRead; // … Playlist freigeben, …
end;
EndMod.SetCuePosition(ptRamp1, EndMod.GetCuePosition(ptCueIn)); // … CueIn in Ramp1 umwidmen und …
EndMod.SetCuePosition(ptCueIn, TempCuePosition); // … ursprüngliches CueIn wiederherstellen
end;
if EndMod.GetCuePosition(ptOutro) = 0 then begin // Feststellen, ob EndMod Outro-Marker-Marker besitzt, falls nicht, …
TempCuePosition := EndMod.GetCuePosition(ptCueOut); // … ursprüngliches CueOut merken, …
CurrentPlaylist.BeginRead; // … Playlist sperren, …
try
EndMod.AutoSearchPosition(ptCueOut); // … per AutoCue Modulationsende feststellen, …
finally
CurrentPlaylist.EndRead; // … Playlist freigeben, …
end;
EndMod.SetCuePosition(ptOutro, EndMod.GetCuePosition(ptCueOut)
- FADEUPOFFSET); // … CueOut in Outro umwidmen, Ofset berücksichtigen und …
EndMod.SetCuePosition(ptCueOut, TempCuePosition); // … ursprüngliches CueOut wiederherstellen
end;
CueStartTime := EndModStartTime + (EndMod.GetCuePosition(ptRamp1)
- EndMod.GetCuePosition(ptCueIn)) / 86400; // Startzeit der Aufblende
EndTitleCue := EndTitleDuration - (EndTime - frac(CueStartTime)) * 86400; // Länge des Schlußtitels setzen
if (EndTitleCue - TIMINGOFFSET >= EndTitle.GetAudibleDuration -
EndMod.GetAudibleDuration - FADEUPDURATION) OR
(EndTitleCue - TIMINGOFFSET < 0) then // Prüfen, ob CueIn mit Titellänge korrespondiert
BTError('Fehler beim Backtiming: Ausreichend/zuviele Elemente? '
+ 'Korrekte Basiszeit?');
EndMod.SetCuePosition(ptStartNext, EndMod.GetCuePosition(ptRamp1) + 0.1); // Start des Schlußtitels setzen
if EndTitle.GetCuePosition(ptCueIn) - TIMINGOFFSET >= 0 then // Prüfen, ob Offset zu groß
EndTitle.SetCuePosition(ptCueIn, EndTitleCue - TIMINGOFFSET); // CueIn des Schlußtitels setzen, ggf. Offset berücksichtigen
EndTitle.GetVolumeEnvelope.AddPoint
(0, STARTLEVEL, 'FadeInBegin'); // Hüllkurvenpunkt (HkP) am Fileanfang
EndTitle.GetVolumeEnvelope.AddPoint
(EndTitleCue, STARTLEVEL, 'FadeInStart'); // HkP unten zu Beginn der Blase
EndTitle.GetVolumeEnvelope.AddPoint
(EndTitleCue + FADEINDURATION, MODLEVEL, 'ModLevelStart'); // HkP oben zu Beginn der Blase
EndTitle.GetVolumeEnvelope.AddPoint
(EndTitleCue + Endmod.GetCuePosition(ptOutro)
- EndMod.GetCuePosition(ptRamp1), MODLEVEL, 'FadeUpStart'); // HkP unten zum Mod-Ende
EndTitle.GetVolumeEnvelope.AddPoint
(EndTitleCue + EndMod.GetCuePosition(ptOutro)
- EndMod.GetCuePosition(ptRamp1) + FADEUPDURATION, 0, 'FadeUpEnd'); // HkP oben zum Mod-Ende
end;
procedure OnExecuteCommand(Command: string);
begin
if (Command = BUTTONCMD) AND NOT PlzBacktime then begin // Backtiming für Mixdown einschalten
PlzBacktime := true; // Zustand merken
ButtonOn; // Knopf leuchten lassen
if CurrentPlaylist.GetCount < 4 then // Mecker, wenn zu wenig Fleisch
BTError('Zu wenige Elemente in der Playlist')
else
FindBacktimingItems;
if NOT BacktimeError then // Wenn alles karl, …
Backtiming; // … los geht's!
end
else if (Command = BUTTONCMD) AND PlzBacktime then begin // Backtiming ausschalten
PlzBacktime := false;
BacktimeError := false;
ButtonOff;
ClearBacktiming(EndTitle); // Schlußtitel auf urspr. CueIn zurücksetzen und HkP löschen
if SET3PLAYERS then
CurrentPlaylist.SetPlayerCount(PlayerCount); // Playeranzahl zurücksetzen
end;
if Command = 'SET2PLAYERS' then
CurrentPlaylist.SetPlayerCount(2); // Hilfskommando zum Zurücksetzen der Playeranzahl
end;
procedure OnPlayerStateChange(PlaylistIndex: integer; PlayerIndex: integer;
OldState: TPlayerState; NewState: TPlayerState; Item: IPlaylistItem);
begin
if NewState = psPlaying then begin // Bei Playerstart …
if (Item <> EndTitle) AND (Item <> EndMod) then begin
if CurrentPlaybackControl.GetAutomation then begin // … und Automatikbetrieb …
ClearBacktiming(EndTitle); // … Backtiming neu berechnen, …
FindBacktimingItems; // … Vorbereitungen treffen …
if NOT BacktimeError then
Backtiming; // … und ggf. Backtiming anstoßen
end;
end;
if SET3PLAYERS AND (CurrentPlaylist.GetPlayerCount < 3) // Wenn Abmod beginnt, …
AND (Item = EndMod) then begin
CurrentPlaylist.SetPlayerCount(3); // … ggf. zusätzlichen Player einsetzen …
end;
end
else if (Item = EndTitle) AND (NewState = psStopped) then // … und nach Schlußtitel …
if SET3PLAYERS then
CurrentPlaylist.SetPlayerCount(PlayerCount); // … wieder zurücksetzen
end;
procedure OnUnload; // Bei Programmstop …
begin
if PlzBacktime then
ClearBacktiming(EndTitle); // Schlußtitel auf urspr. CueIn zurücksetzen und HkP löschen
if SET3PLAYERS then
CurrentPlaylist.SetPlayerCount(PlayerCount); // … wieder zurücksetzen
end;
begin
end. // Punkt.