Skip to content

Instantly share code, notes, and snippets.

@lukepighetti
Created January 30, 2024 15:15
Show Gist options
  • Save lukepighetti/f15e3eb76e3b06dd7fde297863ec8bcf to your computer and use it in GitHub Desktop.
Save lukepighetti/f15e3eb76e3b06dd7fde297863ec8bcf to your computer and use it in GitHub Desktop.
Extracting markers for YouTube channels in Dart
import 'dart:io';
import 'package:xml/xml.dart';
Future<void> main() async {
final str = File('./markers.fcpxmld/Info.fcpxml').readAsStringSync();
final xml = XmlDocument.parse(str);
final markers = xml.findAllElements('marker');
for (final x in markers) {
var start = x.getAttribute('start')!.asDuration;
final value = x.getAttribute('value') as String;
final pOffset = x.parent!.getAttribute('offset')!.asDuration;
final pStart = x.parent!.getAttribute('start')!.asDuration;
final pos = pOffset + start - pStart;
final h = pos.inHours;
final m = pos.inMinutes - h * 60;
final s = pos.inSeconds - h * 60 - m * 60;
final buf = StringBuffer();
if (h != 0) buf.write('$h:');
buf.write('$m:');
buf.write('$s'.padLeft(2, '0'));
buf.write(' $value');
print(buf.toString());
}
}
extension on String {
Duration get asDuration {
final parts = replaceAll('s', '').split('/');
final numerator = int.tryParse(parts.elementAtOrNull(0) ?? '') ?? 0;
final denominator = int.tryParse(parts.elementAtOrNull(1) ?? '') ?? 1;
return Duration(milliseconds: (numerator / denominator * 1000).round());
}
}
0:18 Form request
0:17 Form request
0:30 Mario twitter
0:36 Lifesum
1:05 Downloading the app
2:21 screenshots
3:52 Listing page
6:36 Landing screen
7:47 Onboarding
10:59 Onboarding Value Prop
12:13 Onboarding Authentication
12:37 Onboarding Summary
15:30 Paywall
16:08 Home screen
16:14 Water tracking & Siri Shortcut
16:49 Nutrition Tracking
19:12 Intermittent Fasting + Microonboarding
21:39 Paywall B
22:34 Intermittent fasting continued
24:36 Notifications request
25:00 Intermittent fasting continued
26:49 Life score (bounced)
28:07 Lots of integrations
28:25 Feature metrics discussion
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE fcpxml>
<fcpxml version="1.11">
<resources>
<format id="r1" name="FFVideoFormat1080p60" frameDuration="100/6000s" width="1920" height="1080" colorSpace="1-1-1 (Rec. 709)"/>
<media id="r2" name="Merged" uid="0gWJ9hxFST+rSHUoctbrmg" modDate="2024-01-30 09:12:04 -0500">
<sequence format="r1" duration="59113000/30000s" tcStart="0s" tcFormat="NDF" audioLayout="stereo" audioRate="48k">
<spine>
<clip offset="0s" name="jan-30" duration="59105000/30000s" format="r3" tcFormat="NDF">
<adjust-transform position="29.3519 0"/>
<adjust-volume amount="-7.54175dB"/>
<video ref="r4" offset="0s" duration="59105000/30000s">
<audio ref="r4" lane="-8" offset="0s" duration="1418520000/720000s" role="dialogue.dialogue-8" srcCh="8"/>
<audio ref="r4" lane="-7" offset="0s" duration="1418520000/720000s" role="dialogue.dialogue-7" srcCh="7"/>
<audio ref="r4" lane="-6" offset="0s" duration="1418520000/720000s" role="dialogue.dialogue-6" srcCh="6"/>
<audio ref="r4" lane="-5" offset="0s" duration="1418520000/720000s" role="dialogue.dialogue-5" srcCh="5"/>
<audio ref="r4" lane="-4" offset="0s" duration="1418520000/720000s" role="dialogue.dialogue-4" srcCh="4"/>
<audio ref="r4" lane="-3" offset="0s" duration="1418520000/720000s" role="dialogue.dialogue-3" srcCh="3"/>
<audio ref="r4" lane="-2" offset="0s" duration="1418520000/720000s" role="dialogue.dialogue-2" srcCh="2"/>
<audio ref="r4" lane="-1" offset="0s" duration="1418520000/720000s" role="dialogue.dialogue-1" srcCh="1"/>
</video>
<asset-clip ref="r5" lane="1" offset="122900/6000s" name="jan-30-iphone" start="2096900/6000s" duration="116997000/60000s" format="r6" tcFormat="NDF" audioRole="dialogue">
<adjust-transform position="-60.8056 0.0272634"/>
</asset-clip>
<audio-channel-source srcCh="1" role="dialogue.dialogue-1"/>
<audio-channel-source srcCh="2" role="dialogue.dialogue-2"/>
<audio-channel-source srcCh="3" role="dialogue.dialogue-3"/>
<audio-channel-source srcCh="4" role="dialogue.dialogue-4"/>
<audio-channel-source srcCh="5" role="dialogue.dialogue-5"/>
<audio-channel-source srcCh="6" role="dialogue.dialogue-6"/>
<audio-channel-source srcCh="7" role="dialogue.dialogue-7"/>
<audio-channel-source srcCh="8" role="dialogue.dialogue-8"/>
</clip>
<gap name="Gap" offset="59105000/30000s" start="3600s" duration="8000/30000s"/>
</spine>
</sequence>
</media>
<format id="r3" name="FFVideoFormat720p60" frameDuration="500/30000s" width="1280" height="720" colorSpace="1-1-6"/>
<asset id="r4" name="jan-30" uid="A2155303CC70ABAC492DACF87AD06F59" start="0s" duration="59105000/30000s" hasVideo="1" format="r3" hasAudio="1" videoSources="1" audioSources="1" audioChannels="8" audioRate="44100">
<media-rep kind="original-media" sig="A2155303CC70ABAC492DACF87AD06F59" src="file:///Users/lukepighetti/Movies/Library.fcpbundle/Jan%2030%20app%20review/Original%20Media/jan-30.mov">
<bookmark>Ym9va1QDAAAAAAQQMAAAAFHxnOETy/rHO33iiq55/NoUpeIvVfum5s13332ZC1mUUAIAAAQAAAADAwAAABgAKAUAAAABAQAAVXNlcnMAAAAMAAAAAQEAAGx1a2VwaWdoZXR0aQYAAAABAQAATW92aWVzAAARAAAAAQEAAExpYnJhcnkuZmNwYnVuZGxlAAAAEQAAAAEBAABKYW4gMzAgYXBwIHJldmlldwAAAA4AAAABAQAAT3JpZ2luYWwgTWVkaWEAAAoAAAABAQAAamFuLTMwLm1vdgAAHAAAAAEGAAAQAAAAIAAAADQAAABEAAAAYAAAAHwAAACUAAAACAAAAAQDAACEXAAAAAAAAAgAAAAEAwAAsscDAAAAAAAIAAAABAMAAOHHAwAAAAAACAAAAAQDAADFt4cAAAAAAAgAAAAEAwAAPr5+BwAAAAAIAAAABAMAAIK+fgcAAAAACAAAAAQDAAAev34HAAAAABwAAAABBgAAzAAAANwAAADsAAAA/AAAAAwBAAAcAQAALAEAAAgAAAAABAAAQcW0nKfQc7cYAAAAAQIAAAEAAAAAAAAADwAAAAAAAAAAAAAAAAAAAAgAAAAEAwAABQAAAAAAAAAEAAAAAwMAAPUBAAAIAAAAAQkAAGZpbGU6Ly8vDAAAAAEBAABNYWNpbnRvc2ggSEQIAAAABAMAAACQgpbnAAAACAAAAAAEAABBxVGOmIAAACQAAAABAQAARTgwQ0VEMTAtNEVENC00N0MyLTk1M0EtNEUyMDc2QzUxNUMzGAAAAAECAACBAAAAAQAAAO8TAAABAAAAAAAAAAAAAAABAAAAAQEAAC8AAAAAAAAAAQUAAMwAAAD+////AQAAAAAAAAAQAAAABBAAAKgAAAAAAAAABRAAADwBAAAAAAAAEBAAAHABAAAAAAAAQBAAAGABAAAAAAAAAiAAADwCAAAAAAAABSAAAKwBAAAAAAAAECAAALwBAAAAAAAAESAAAPABAAAAAAAAEiAAANABAAAAAAAAEyAAAOABAAAAAAAAICAAABwCAAAAAAAAMCAAAEgCAAAAAAAAAcAAAJABAAAAAAAAEcAAACAAAAAAAAAAEsAAAKABAAAAAAAAENAAAAQAAAAAAAAA</bookmark>
</media-rep>
<metadata>
<md key="com.apple.proapps.studio.rawToLogConversion" value="0"/>
<md key="com.apple.proapps.spotlight.kMDItemProfileName" value="(1-1-6)"/>
<md key="com.apple.proapps.studio.cameraISO" value="0"/>
<md key="com.apple.proapps.studio.cameraColorTemperature" value="0"/>
<md key="com.apple.proapps.spotlight.kMDItemCodecs">
<array>
<string>H.264</string>
<string>MPEG-4 AAC</string>
</array>
</md>
<md key="com.apple.proapps.mio.ingestDate" value="2024-01-30 09:05:17 -0500"/>
</metadata>
</asset>
<asset id="r5" name="jan-30-iphone" uid="1768EB51B1045D73FD5DC2BAE1F3BF28" start="0s" duration="137966469/60000s" hasVideo="1" format="r6" hasAudio="1" videoSources="1" audioSources="1" audioChannels="2" audioRate="48000">
<media-rep kind="original-media" sig="1768EB51B1045D73FD5DC2BAE1F3BF28" src="file:///Users/lukepighetti/Movies/Library.fcpbundle/Jan%2030%20app%20review/Original%20Media/jan-30-iphone.mov">
<bookmark>Ym9va1wDAAAAAAQQMAAAADa/y+hcLU+Rrhbd4E96Ia0G9ChciAix2i6gGPXCvEKnWAIAAAQAAAADAwAAABgAKAUAAAABAQAAVXNlcnMAAAAMAAAAAQEAAGx1a2VwaWdoZXR0aQYAAAABAQAATW92aWVzAAARAAAAAQEAAExpYnJhcnkuZmNwYnVuZGxlAAAAEQAAAAEBAABKYW4gMzAgYXBwIHJldmlldwAAAA4AAAABAQAAT3JpZ2luYWwgTWVkaWEAABEAAAABAQAAamFuLTMwLWlwaG9uZS5tb3YAAAAcAAAAAQYAABAAAAAgAAAANAAAAEQAAABgAAAAfAAAAJQAAAAIAAAABAMAAIRcAAAAAAAACAAAAAQDAACyxwMAAAAAAAgAAAAEAwAA4ccDAAAAAAAIAAAABAMAAMW3hwAAAAAACAAAAAQDAAA+vn4HAAAAAAgAAAAEAwAAgr5+BwAAAAAIAAAABAMAAIu/fgcAAAAAHAAAAAEGAADUAAAA5AAAAPQAAAAEAQAAFAEAACQBAAA0AQAACAAAAAAEAABBxbScq/XJ+RgAAAABAgAAAQAAAAAAAAAPAAAAAAAAAAAAAAAAAAAACAAAAAQDAAAFAAAAAAAAAAQAAAADAwAA9QEAAAgAAAABCQAAZmlsZTovLy8MAAAAAQEAAE1hY2ludG9zaCBIRAgAAAAEAwAAAJCClucAAAAIAAAAAAQAAEHFUY6YgAAAJAAAAAEBAABFODBDRUQxMC00RUQ0LTQ3QzItOTUzQS00RTIwNzZDNTE1QzMYAAAAAQIAAIEAAAABAAAA7xMAAAEAAAAAAAAAAAAAAAEAAAABAQAALwAAAAAAAAABBQAAzAAAAP7///8BAAAAAAAAABAAAAAEEAAAsAAAAAAAAAAFEAAARAEAAAAAAAAQEAAAeAEAAAAAAABAEAAAaAEAAAAAAAACIAAARAIAAAAAAAAFIAAAtAEAAAAAAAAQIAAAxAEAAAAAAAARIAAA+AEAAAAAAAASIAAA2AEAAAAAAAATIAAA6AEAAAAAAAAgIAAAJAIAAAAAAAAwIAAAUAIAAAAAAAABwAAAmAEAAAAAAAARwAAAIAAAAAAAAAASwAAAqAEAAAAAAAAQ0AAABAAAAAAAAAA=</bookmark>
</media-rep>
<metadata>
<md key="com.apple.proapps.studio.rawToLogConversion" value="0"/>
<md key="com.apple.proapps.spotlight.kMDItemProfileName" value="HD (1-1-1)"/>
<md key="com.apple.proapps.studio.cameraISO" value="0"/>
<md key="com.apple.proapps.studio.cameraColorTemperature" value="0"/>
<md key="com.apple.proapps.spotlight.kMDItemCodecs">
<array>
<string>H.264</string>
<string>MPEG-4 AAC</string>
</array>
</md>
<md key="com.apple.proapps.mio.ingestDate" value="2024-01-30 09:05:17 -0500"/>
</metadata>
</asset>
<format id="r6" frameDuration="1000/60000s" width="1080" height="1920" colorSpace="1-1-1 (Rec. 709)"/>
<asset id="r7" name="Screenshot 2024-01-30 at 9.18.46 AM" uid="9040F494E938528D007D6028004B00B3" start="0s" duration="0s" hasVideo="1" format="r8" videoSources="1">
<media-rep kind="original-media" sig="9040F494E938528D007D6028004B00B3" src="file:///Users/lukepighetti/Movies/Library.fcpbundle/Jan%2030%20app%20review/Original%20Media/Screenshot%202024-01-30%20at%209.18.46%20AM.png">
<bookmark>Ym9va3ADAAAAAAQQMAAAAPbu90Ep8g/S5G//9fI28TD9Z5cDqAozGVMb+E164hfIbAIAAAQAAAADAwAAABgAKAUAAAABAQAAVXNlcnMAAAAMAAAAAQEAAGx1a2VwaWdoZXR0aQYAAAABAQAATW92aWVzAAARAAAAAQEAAExpYnJhcnkuZmNwYnVuZGxlAAAAEQAAAAEBAABKYW4gMzAgYXBwIHJldmlldwAAAA4AAAABAQAAT3JpZ2luYWwgTWVkaWEAACcAAAABAQAAU2NyZWVuc2hvdCAyMDI0LTAxLTMwIGF0IDkuMTguNDYgQU0ucG5nABwAAAABBgAAEAAAACAAAAA0AAAARAAAAGAAAAB8AAAAlAAAAAgAAAAEAwAAhFwAAAAAAAAIAAAABAMAALLHAwAAAAAACAAAAAQDAADhxwMAAAAAAAgAAAAEAwAAxbeHAAAAAAAIAAAABAMAAD6+fgcAAAAACAAAAAQDAACCvn4HAAAAAAgAAAAEAwAAJc5+BwAAAAAcAAAAAQYAAOgAAAD4AAAACAEAABgBAAAoAQAAOAEAAEgBAAAIAAAAAAQAAEHFtJ5kO9IeGAAAAAECAAABAAAAAAAAAA8AAAAAAAAAAAAAAAAAAAAIAAAABAMAAAUAAAAAAAAABAAAAAMDAAD1AQAACAAAAAEJAABmaWxlOi8vLwwAAAABAQAATWFjaW50b3NoIEhECAAAAAQDAAAAkIKW5wAAAAgAAAAABAAAQcVRjpiAAAAkAAAAAQEAAEU4MENFRDEwLTRFRDQtNDdDMi05NTNBLTRFMjA3NkM1MTVDMxgAAAABAgAAgQAAAAEAAADvEwAAAQAAAAAAAAAAAAAAAQAAAAEBAAAvAAAAAAAAAAEFAADMAAAA/v///wEAAAAAAAAAEAAAAAQQAADEAAAAAAAAAAUQAABYAQAAAAAAABAQAACMAQAAAAAAAEAQAAB8AQAAAAAAAAIgAABYAgAAAAAAAAUgAADIAQAAAAAAABAgAADYAQAAAAAAABEgAAAMAgAAAAAAABIgAADsAQAAAAAAABMgAAD8AQAAAAAAACAgAAA4AgAAAAAAADAgAABkAgAAAAAAAAHAAACsAQAAAAAAABHAAAAgAAAAAAAAABLAAAC8AQAAAAAAABDQAAAEAAAAAAAAAA==</bookmark>
</media-rep>
<metadata>
<md key="com.apple.proapps.studio.rawToLogConversion" value="0"/>
<md key="com.apple.proapps.spotlight.kMDItemProfileName" value="Studio Display"/>
<md key="com.apple.proapps.studio.cameraISO" value="0"/>
<md key="com.apple.proapps.studio.cameraColorTemperature" value="0"/>
<md key="com.apple.proapps.mio.ingestDate" value="2024-01-30 09:18:54 -0500"/>
</metadata>
</asset>
<format id="r8" name="FFVideoFormatRateUndefined" width="3280" height="2114"/>
</resources>
<library location="file:///Users/lukepighetti/Movies/Library.fcpbundle/">
<event name="Jan 30 app review" uid="833560F3-B979-487D-BCDE-AE04094039E1">
<project name="Untitled Project" uid="2B4E19CF-7304-412A-9301-C782C2A9442D" modDate="2024-01-30 09:34:17 -0500">
<sequence format="r1" duration="11586100/6000s" tcStart="0s" tcFormat="NDF" audioLayout="stereo" audioRate="48k">
<spine>
<ref-clip ref="r2" offset="0s" name="Merged" start="123500/6000s" duration="13600/6000s">
<adjust-volume amount="-7dB">
<param name="amount">
<fadeIn type="easeIn" duration="1191595/720000s"/>
<fadeOut type="easeIn" duration="112984/720000s"/>
</param>
</adjust-volume>
</ref-clip>
<ref-clip ref="r2" offset="13600/6000s" name="Merged" start="242000/6000s" duration="156100/6000s">
<adjust-volume>
<param name="amount">
<fadeIn type="easeIn" duration="203701/720000s"/>
</param>
</adjust-volume>
<marker start="284/5s" duration="100/6000s" value="Form request"/>
</ref-clip>
<ref-clip ref="r2" offset="169700/6000s" name="Merged" start="406200/6000s" duration="11416400/6000s">
<adjust-volume>
<param name="amount">
<fadeOut type="easeIn" duration="2088000/720000s"/>
</param>
</adjust-volume>
<video ref="r7" lane="1" offset="832800/6000s" name="Screenshot 2024-01-30 at 9.18.46 AM" start="3600s" duration="19300/6000s">
<adjust-transform position="-3.21296 -1.37037" scale="1.3 1.3"/>
</video>
<marker start="284/5s" duration="100/6000s" value="Form request"/>
<marker start="70s" duration="100/6000s" value="Mario twitter"/>
<marker start="1132/15s" duration="100/6000s" value="Lifesum"/>
<marker start="3137/30s" duration="100/6000s" value="Downloading the app"/>
<marker start="2713/15s" duration="100/6000s" value="screenshots"/>
<marker start="16297/60s" duration="100/6000s" value="Listing page"/>
<marker start="8717/20s" duration="100/6000s" value="Landing screen"/>
<marker start="2536/5s" duration="100/6000s" value="Onboarding"/>
<marker start="20957/30s" duration="100/6000s" value="Onboarding Value Prop"/>
<marker start="3093/4s" duration="100/6000s" value="Onboarding Authentication"/>
<marker start="15941/20s" duration="100/6000s" value="Onboarding Summary"/>
<marker start="29089/30s" duration="100/6000s" value="Paywall"/>
<marker start="5038/5s" duration="100/6000s" value="Home screen"/>
<marker start="4055/4s" duration="100/6000s" value="Water tracking &amp; Siri Shortcut"/>
<marker start="31469/30s" duration="100/6000s" value="Nutrition Tracking"/>
<marker start="35771/30s" duration="100/6000s" value="Intermittent Fasting + Microonboarding"/>
<marker start="40177/30s" duration="100/6000s" value="Paywall B"/>
<marker start="83623/60s" duration="100/6000s" value="Intermittent fasting continued"/>
<marker start="9097/6s" duration="100/6000s" value="Notifications request"/>
<marker start="23101/15s" duration="100/6000s" value="Intermittent fasting continued"/>
<marker start="24737/15s" duration="100/6000s" value="Life score (bounced)"/>
<marker start="34547/20s" duration="100/6000s" value="Lots of integrations"/>
<marker start="20939/12s" duration="100/6000s" value="Feature metrics discussion"/>
</ref-clip>
</spine>
</sequence>
</project>
</event>
</library>
</fcpxml>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment