Autor | Lok'tar ogar
Führung
Basierend auf der Entwicklungspraxis der Textvorlagen der Duka Editing APP stellt dieser Artikel die technische Lösung der Renderfunktionen für statische Textvorlagen in Videobearbeitungsszenarien vor. Als Obermenge der Rich-Text-Rendering-Lösung kann diese technische Lösung auf andere Szenarien erweitert werden, die ein komplexes Rich-Text-Rendering erfordern.
Der Volltext umfasst 6745 Wörter und die erwartete Lesezeit beträgt 17 Minuten.
Vorgeschmack
Textvorlagen-Effektanzeige:
△Anwendung der Textvorlage in der Duka-Bearbeitung
01 Hintergrund
Eine der wichtigsten Wettbewerbsfähigkeiten von Tools zur Videoerstellung ist ihre reichhaltige Materialbibliothek, einschließlich verschiedener Videomaterialien, Audiomaterialien, Aufklebermaterialien und so weiter. Auch die Textvorlage ist fester Bestandteil. Die Textvorlage bietet eine Rich-Text-Bearbeitungsfunktion, mit der Benutzer schöner gestaltete Textinformationen in das Video einfügen und so die Vielfalt des Videomaterials erhöhen können. Darüber hinaus können Benutzer durch den voreingestellten Stil bequemer die für sie passende Textvorlage auswählen, was Zeit bei der Materialauswahl spart und die Benutzererfahrung verbessert. In der frühen Version von Duka haben wir den Materialtyp der Textvorlage nicht bereitgestellt. Um die Wettbewerbsfähigkeit von Produkten zu verbessern und die Durchdringungsrate von Materialien zu erhöhen, haben wir bestimmte Forschungs- und Entwicklungsarbeiten durchgeführt und schließlich die Textvorlagenmaterialien auf den Markt gebracht. Diese Textvorlagenmaterialien können nicht nur die Bedürfnisse der Benutzer erfüllen, sondern den Benutzern auch kreativere Inspiration und Ideen bieten. Gleichzeitig aktualisieren und optimieren wir unsere Materialbibliothek ständig, um sicherzustellen, dass Benutzer die neuesten und qualitativ hochwertigsten Materialressourcen erhalten. Die Grafiken und Textstile, die die Textvorlage darstellen muss, sind relativ komplex.Die von der Duka-Textvorlage unterstützten Funktionen sind unten aufgeführt:
02 Gesamtdesign
Basierend auf der von uns erstellten Materialplattform haben wir eine neue Art von Textvorlagen hinzugefügt und Materialbearbeitungs-, Vorschau-, Konfigurations- und Online-Funktionen auf der Materialplattform bereitgestellt. Durch die Kombination von Materialproduktion und Vorschau können Sie den gerade angepassten Effekt auf derselben Oberfläche in der Vorschau anzeigen, direkt mit der Schriftbibliothek von Duka abgleichen und Bildressourcen direkt ändern. Diese Materialherstellungsmethode ist in hohem Maße wiederverwendbar: Durch eine Textvorlage, das Ändern eines Hintergrundbilds und das Hinzufügen eines Strichs kann direkt eine andere Textvorlage erstellt werden. Nach dem Veröffentlichen dieser Vorlage und dem Exportieren des Wirkungsdiagramms wird es zur Überprüfung in die Warteschlange aufgenommen und kann nach der Überprüfung konfiguriert und gestartet werden. Bis jetzt haben wir 361 Sätze von Textvorlagen gestartet und den vollständigen Link von [Materialproduktion] – [Vorschau der Materialplattform] – [Materiallieferung und Client-Laden] – [Client-Rendering] fertiggestellt.
03 Funktionsrealisierung
3.1 Materialherstellung
Gegenwärtig übernimmt das Mainstream-Materialformat in der Videobearbeitungsbranche normalerweise Ressourcendateien und Konfigurationsdateien (Beschreibungsdateien). Zu den Ressourcendateien gehören Bildressourcen und Schriftdateien, während Konfigurationsdateien hauptsächlich verwendet werden, um die Satzattribute und Wiedergabeparameter von Textvorlagen zu beschreiben. Der Vorteil dieser Methode besteht darin, dass die relevanten Merkmale auf der Produktionsseite nur durch bestimmte Felder beschrieben werden müssen und auf der Rendering-Seite dargestellt werden können. Diese Methode ist sehr flexibel und kann verwandte Funktionen von einfach bis komplex gemäß den Anforderungen bestimmter Szenarien iterieren, während die Implementierungskosten relativ gering sind. Der Nachteil ist jedoch, dass die Form der Materialherstellung kundenspezifisch ist, was einen gewissen Konstruktions- und Lernaufwand erfordert. Darüber hinaus gibt es eine weitere Produktionsmethode für professionelle Designsoftware am Beispiel von Photoshop (PS). PS verfügt über relativ ausgereifte Dateiformatdokumente, einschließlich verschiedener Datenstrukturen, und kann PSD-Dateien direkt verwenden, um Grafik- und Textattribute für die Wiedergabe zu analysieren. Der Vorteil dieser Methode besteht darin, dass die Materialherstellungsmethode allgemeiner ist und das Design fast keine Lernkosten verursacht. Der Nachteil ist jedoch, dass einige Funktionen, die wir benötigen, nicht einfach von PSD erfüllt werden können, wie z. B. der mehrschichtige Schatteneffekt, der durch Übereinanderlegen mehrerer Textfelder erzielt wird. Beim Ändern von Textinhalten müssen wir diese Textfelder gleichzeitig ändern, also müssen wir sie als Gruppe behandeln, und die Logik wird komplizierter. Wenn es durch eine Konfigurationsdatei beschrieben wird, kann es ohne komplizierte logische Verarbeitung direkt mehrschichtiges Zeichnen ausführen. In Anbetracht der Machbarkeit von Unternehmens-ROI und kurzfristigen Online-Funktionen haben wir die erste Methode übernommen, uns auf die Materialproduktionsstandards des Butter Camera-Teams gestützt und eine JSON-Struktur zur Beschreibung von Satzattributen und Rendering-Parametern entworfen.
3.2 Seitenrendering
Im Videobearbeitungsszenario erfordert die Textverarbeitung zwei Teile: Textlayout und Textzeichnung. Für den Textsatz verwendet die iOS-Plattform das zugrunde liegende Framework von CoreText für die Satzverarbeitung, während Android die Ergebnisse der zugrunde liegenden Schriftartverarbeitung von FreeType über FontMetrics usw. abrufen kann. Unabhängig davon, ob ein Text als Ganzes formatiert wird oder die Position jedes Textes separat berechnet wird, ist der Leistungsverbrauch der gesamten Verarbeitung gleich. In Bezug auf das Zeichnen von Text ist es notwendig, ein Gleichgewicht zwischen Leistungsaufwand und Entwicklungskosten zu finden. Am Ende übernahm iOS das QuartzCore-Framework und Android verwendete Canvas zum Zeichnen von Text. Auf diese Weise kann der Text bei der Vorschau direkt in der Ansicht präsentiert werden, was die Bearbeitung und Vorschau in Echtzeit unterstützt. Wenn das Video exportiert werden muss, verarbeiten wir es als Sticker und fügen es dem Video hinzu. Am Beispiel von iOS sieht die Komponentenarchitektur von Huazi wie folgt aus:
3.3 Design der Beschreibungsdatei
Wie oben erwähnt, verwenden wir JSON-Dateien, um die Satzattribute und Rendering-Parameter der Textvorlage zu beschreiben. Nachdem die Ressourcen an den Kunden geliefert wurden, analysiert der Kunde die entsprechenden Parameter, um den Satz der Textvorlage und die endgültige Effektpräsentation durchzuführen . Folgende Inhalte werden in die Beschreibungsdatei eingebunden:
(1) Textlayoutattribute
- Grundlinie: Grundlinie des Zeichens, Grundlinie ist eine virtuelle Linie
- Aufstieg: Der empfohlene Abstand vom höchsten Punkt der Glyphe zur Grundlinie
- Abstieg: Der empfohlene Abstand vom tiefsten Punkt der Glyphe zur Grundlinie
- Leading: Zeilenabstand, d. h. der Abstand zwischen dem Abstieg der vorherigen Zeile und dem Anstieg der nächsten Zeile
- Fortschrittsbreite: Der Abstand vom Ursprung zum nächsten Glyphenursprung
- linke Peilung: Die Entfernung vom Ursprung zum äußersten linken Rand der Glyphe
- Peilung auf der rechten Seite: Der Abstand von der äußersten rechten Seite der Glyphe zum Ursprung der nächsten Glyphe
- Begrenzungsrahmen: das kleinste Rechteck, das die Glyphe enthält
- x-Höhe: bezieht sich allgemein auf den empfohlenen Abstand vom höchsten Punkt des Kleinbuchstaben x zur Grundlinie
- Kappenhöhe: bezieht sich im Allgemeinen auf den empfohlenen Abstand vom höchsten Punkt von H oder I zur Grundlinie
(2) Kombination von Textobjekten Die folgende Abbildung ist ein Beispiel für die Kombination von zwei Textzeichenbereichen
3.4 Satz- und Zeichenprozess
In unserer Textvorlage sind Satz und Zeichnung untrennbar und müssen zur Verarbeitung in die Codelogik eingestreut werden. Unser Zeichenschritt besteht darin, Schicht für Schicht von der untersten Schicht zur obersten Schicht zu zeichnen, aber da einige Zeichenprozesse viel Zeit in Anspruch nehmen, verwenden wir die asynchrone Zeichentechnologie, um das Blockieren des Hauptfadens zu vermeiden. Beim asynchronen Zeichnen haben wir einige zeitaufwändige Zeichenprozesse zur Verarbeitung in den Hintergrundthread gestellt, um die normale Verwendung der Benutzer nicht zu beeinträchtigen. Gleichzeitig berechnen wir im Prozess des asynchronen Zeichnens auch das Textlayout, um im anschließenden Zeichenprozess schnell die relevanten Informationen des Textes zu erhalten und so die Zeicheneffizienz zu verbessern. Im Allgemeinen können wir durch die Verwendung der asynchronen Zeichenmethode sicherstellen, dass der Satz- und Zeichenprozess der Textvorlage reibungslos abläuft, ohne den Benutzer zu stark zu stören.
04 Schwierigkeiten und Herausforderungen
1. Ausrichtung von Multi-Terminal-Effekten
Unser Projekt unterstützt Web-, iOS- und Android-Rendering, aber weil die allgemeine Cross-End-Lösung OpenGL-Rendering auf der untersten Ebene verwenden muss und die damaligen Personalbeschränkungen es schwierig machten, dies kurzfristig zu erreichen. Daher haben wir eine unabhängige Multi-Terminal-Rendering-Methode eingeführt, und jede Plattform verfügt über eine unabhängige Rendering-Lösung. Diese Methode bringt auch ein Problem mit sich: Der Rendering-Effekt verschiedener Plattformen ist unterschiedlich. Um dieses Problem zu lösen, müssen wir die Konsistenz von Multi-Terminal-Effekten sicherstellen. Da es schwierig ist, die Unterschiede auf technischer Ebene auszugleichen, haben wir uns entschieden, Konsistenz durch die Vereinheitlichung von Regeln und Standards zu erreichen. Beim Entwerfen des Formats der json-Datei haben wir die Standards für das Multi-Terminal-Rendering vereinheitlicht, z. B. ob die Anfangsposition der Textdekoration relativ zum Text in der oberen linken Ecke ausgerichtet oder zentriert ist und der Ursprung der Koordinaten ist einheitlich. Gleichzeitig haben wir auch die von den entsprechenden Parametern verwendeten Einheiten vereinheitlicht, um die Konsistenz des endgültigen Rendering-Effekts so weit wie möglich zu gewährleisten. Auf diese Weise können wir, egal auf welcher Plattform gerendert wird, konsistente Ergebnisse erzielen, wodurch die Benutzererfahrung einheitlicher und besser wird.
2. Textvorsatz
In der Textvorlage unterteilen wir die Schriftgröße in zwei Arten: feste Schriftgröße und nicht feste Schriftgröße. Für eine feste Schriftgröße können wir direkt die Berechnung und das Zeichnen des Textlayouts durchführen. Bei Schriftarten mit nicht fester Schriftgröße müssen wir jedoch Vorkalkulationen durchführen, um die entsprechende Schriftgröße unter dem aktuellen Textinhalt zu berechnen. Einige Lösungen verwenden hier die Dichotomie-Methode, stellen zuerst einen größeren Schriftgrößenwert ein und nähern sich allmählich dem richtigen Wert im Bereich von 0 bis zum Schriftgrößenwert, aber dies verursacht tatsächlich unnötigen Zeitverlust, kombiniert mit der grundlegenden Logik und den Einschränkungen von Text Layoutbedingungen können wir einen Algorithmus mit einer Zeitkomplexität nahe O(1) erstellen: Berechnen Sie die maximale Zeichenhöhe -> berechnen Sie die minimale Zeichenhöhe -> berechnen Sie die Zeichenhöhe der längsten Wortzeile -> berechnen Sie die Zeichenhöhe entsprechend auf die Anzahl der Zeilen -> Berechnung der endgültigen Zeichenhöhe -> Berechnung der Schriftgröße anhand der Zeichenhöhe. Wenn die CoreText-Schriftsatztechnologie in iOS verwendet wird, wird in einigen wenigen Fällen der Text, der nicht ausgefüllt werden kann, automatisch abgeschnitten. Die direkte Verwendung der berechneten Schriftgröße führt dazu, dass ein Teil des Textes abgeschnitten wird. Daher sollten die obigen Ergebnisse sein als Schätzergebnisse verwendet, und die Größe wird schrittweise um 1 verringert, bis der Pfad ausgefüllt werden kann.
CGFloat ascent, descent;
UIFont *font = [self.calFont fontWithSize:size];
CTFontRef fontRefMeasure = (__bridge CTFontRef)font;
[attrString addAttribute:(id)kCTFontAttributeName value:(__bridge id)fontRefMeasure range:NSMakeRange(0, attrString.length)];
CTLineRef line = CTLineCreateWithAttributedString((__bridge CFAttributedStringRef)attrString);
CTLineGetTypographicBounds(line, &ascent, &descent, NULL);
//calculate max font size
CGFloat calFontHeight = MIN(height, width);
self.maxFontHeight = calFontHeight;
//calculate min font size
CGFloat maxLine = self.document.maxLine * BDTZBigFontDataOriginScale;
if (maxLine <= 0) {
maxLine = 1;
}
calFontHeight = [self itemWidth] / (maxLine + (maxLine - 1) * (self.leadingRatio * BDTZBigFontDataOriginScale - 1));
self.minFontHeight = MIN(self.maxFontHeight, calFontHeight);
// longest column
int64_t n = 0;
NSArray *strArray = [self.document.content componentsSeparatedByString:@"\n"];
NSString *measureStr = self.document.content;
// 这里是针对多行文本的处理,循环次数为行数,量级较小(一般为1-10行)
for (NSString *str in strArray) {
if (str.length > n) {
n = str.length;
measureStr = str;
}
}
CGFloat fontWidthRatioOrigin = (self.document.fontWidthRatio * BDTZBigFontDataOriginScale);
CGFloat trackingRatio = (self.document.trackingRatio * BDTZBigFontDataOriginScale) * (ascent + descent) / ascent;
CGRect rect = [@"我" boundingRectWithSize:CGSizeMake(CGFLOAT_MAX, CGFLOAT_MAX) options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName:self.calFont} context:nil];
CGFloat fontWidthRatio = fontWidthRatioOrigin > 0 ? fontWidthRatioOrigin * (ascent + descent) / ascent : rect.size.width / rect.size.height;
CGFloat fontHeight = width / (n * fontWidthRatio + n * trackingRatio);
if (strArray.count > 1) {
//calculate font size accoring column count
calFontHeight = [self itemWidth] / (strArray.count + (strArray.count - 1) * (self.leadingRatio * BDTZBigFontDataOriginScale - 1));
//take the min value of the above two font sizes
fontHeight = MIN(fontHeight, calFontHeight);
}
if (fontHeight > self.maxFontHeight) {
fontHeight = self.maxFontHeight;
} else if (fontHeight < self.minFontHeight) {
fontHeight = self.minFontHeight;
}
CGFloat calSize = fontHeight;
calFontHeight = [self calculateFontHeightSize:calSize];
calSize = floorf(calSize / (calFontHeight * (ascent + descent) / ascent) * calSize);
//exact value, calculate repeatedly with frame until the path can be filled
//根据估算结果,将size逐次减1,直至能填入path,此处代码省略
if (calSize <= 0) {
return calSize;
}
calFontHeight = [self calculateFontHeightSize:calSize];
self.fontHeight = calFontHeight * (ascent + descent) / ascent;
self.font = [self.calFont fontWithSize:calSize];
3. Zeichenleistung
Die Echtzeitvorschau der Textvorlage muss häufig gezeichnet werden, was die CPU stark belastet und zu Verzögerungen führt. Um dieses Problem zu lösen, müssen wir asynchrones Zeichnen verwenden. Insbesondere können wir eine asynchrone serielle Warteschlange erstellen, um den Textinhaltsstatus jeder Benutzeroperation zu speichern. Immer wenn der Benutzer eine Änderung vornimmt, stellen wir den aktuellen Status in eine Warteschlange und warten darauf, dass der Hintergrundthread asynchron zeichnet. Nachdem der vorherige Zustand gezogen wurde, nehmen wir den nächsten zu ziehenden Zustand aus der Warteschlange heraus, bis alle Zustände gezogen sind. Auf diese Weise wird ein asynchrones Zeichnen realisiert, um zu verhindern, dass der Haupt-Thread hängen bleibt, und die Ergebnisse jeder Änderung durch den Benutzer werden vollständig dargestellt. Um die Benutzerfreundlichkeit von Textvorlagen weiter zu optimieren, können Sie neben dem asynchronen Zeichnen auch die Verwendung eines Caching-Mechanismus in Betracht ziehen, um die Renderleistung zu verbessern. Wenn der Benutzer die Textvorlage bearbeitet, wird die Textansicht neu gestaltet und gezeichnet. Wenn die gesamte Vorlage jedes Mal neu gezeichnet wird, nimmt dies nicht nur viele CPU-Ressourcen in Anspruch, sondern verringert auch die Benutzererfahrung. Daher können wir den Cache verwenden, um die gezeichnete Vorlagenansicht zu speichern. Wenn der Benutzer den Textinhalt ändert, muss nur der geänderte Teil neu gezeichnet werden, anstatt der gesamten Ansicht. Auf diese Weise können wir die Renderleistung verbessern, gleichzeitig den Ressourcenverbrauch reduzieren und die Reaktionsfähigkeit des Systems verbessern.
4. Speicheroptimierung
Unsere Textvorlagen werden hauptsächlich in Videobearbeitungsszenarien verwendet, und Benutzer müssen die Textvorlagen je nach Situation vergrößern oder verkleinern. Wenn die reine Vektorzeichnungs-Refresh-Methode verwendet wird, wenn der Benutzer die Textvorlage bis zu einem gewissen Grad vergrößert, wird der Speicherverbrauch sehr hoch sein. Darüber hinaus fügen unsere Benutzer normalerweise viele Materialien in den Editor ein, wie Aufkleber, Spezialeffekte und Untertitel usw., und jedes dieser Materialien nimmt viel Speicherplatz ein.Nach einer bestimmten Nutzungsdauer wird der Speicherplatz wahrscheinlich zunehmen auf den OOM-Schwellenwert, wodurch die Anwendung abstürzt. Daher kontrollieren wir derzeit den Speicher einer einzelnen Textvorlage auf weniger als 20 MB und berechnen die Breiten- und Höhenschwellenwerte, die für die Textvorlage erforderlich sind, um die erwartete Klarheit gemäß unterschiedlichen Videobreiten und -höhen zu erreichen, um ein Gleichgewicht zwischen Klarheit zu erreichen und Speicherauslastung.Jede Textvorlage hat einen anderen Balance-Parameter. Obwohl dies nur ein Detail zur Speicheroptimierung ist, hat es eine große Rolle bei der Steuerung der Speichernutzung des Materials und der Online-OOM-Rate gespielt.
05 Epilog
In der Welt der Videobearbeitung ist das Rendern von Rich Text ein ziemlich komplexer Prozess. Was das End-Rendering betrifft, gibt es keine Einheitslösung, sondern nur die am besten geeignete Lösung für eine bestimmte Szene. Beim Entwerfen und Implementieren einer Lösung zum Rendern von Textvorlagen müssen viele Details berücksichtigt werden. Gleichzeitig ist auch ein tiefgreifendes Verständnis der Dateiformate gängiger Designsoftware wie PS und Figma erforderlich. Unser Team bietet technische Lösungen im Zusammenhang mit statischen Textvorlagen, die den häufigeren Rich-Text-Rendering-Szenarien gerecht werden können. Die Gesamtidee ist für Textlayout und Zeichnung ungefähr ähnlich. In diesem Artikel stellen wir grundlegende Konzepte und Rich-Text-Funktionen vor, um den Lesern zu helfen, unsere technischen Lösungen besser zu verstehen. Doch auch bei der von uns angebotenen Lösung sind bei der Umsetzung viele Details zu beachten. Wir müssen Schriftgröße, Farbe, Ausrichtung, Zeichenabstand, Zeilenabstand und andere Faktoren berücksichtigen, um sicherzustellen, dass der gerenderte Rich-Text den erwarteten Effekt erzielen kann. Um den besten Effekt des Rich-Text-Renderings zu erzielen, muss daher viel Zeit und Mühe in Design und Implementierung investiert werden. Nur durch ein tiefes Verständnis der Eigenschaften und Gestaltungsprinzipien von Rich Text können wir den Benutzern ein qualitativ hochwertiges Videobearbeitungserlebnis bieten.
--ENDE--
Empfohlene Lektüre: Sprechen über die Anti-Cheat-Anwendung von Graphalgorithmen in Ereignisszenarien
Serverlos: Flexible Skalierungspraxis basierend auf personalisierten Serviceportraits
Aktionszerlegungsmethode in der Bildanimationsanwendung
Performance Platform Data Acceleration Road
Bearbeitung der AIGC-Videoproduktionsprozess-Anordnungspraxis
Baidu-Ingenieure sprechen über Videoverständnis