Files
media-analyzer/def/architecture/architecture_diagram.svg
2025-08-25 04:03:56 -03:00

646 lines
39 KiB
XML

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Generated by graphviz version 2.42.4 (0)
-->
<!-- Title: MediaAnalyzer Pages: 1 -->
<svg width="648pt" height="720pt"
viewBox="0.00 0.00 647.84 720.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(0.34 0.34) rotate(0) translate(4 2084.29)">
<title>MediaAnalyzer</title>
<polygon fill="white" stroke="transparent" points="-4,4 -4,-2084.29 1875,-2084.29 1875,4 -4,4"/>
<g id="clust1" class="cluster">
<title>cluster_legend</title>
<polygon fill="lightgray" stroke="lightgray" points="8,-1674.04 8,-2057.88 236,-2057.88 236,-1674.04 8,-1674.04"/>
<text text-anchor="middle" x="122" y="-2044.28" font-family="Arial" font-size="12.00">Legend</text>
</g>
<g id="clust2" class="cluster">
<title>cluster_sources</title>
<polygon fill="#1976d2" stroke="#1976d2" points="244,-1853.35 244,-2057.88 494,-2057.88 494,-1853.35 244,-1853.35"/>
<text text-anchor="middle" x="369" y="-2044.28" font-family="Arial" font-size="12.00">Video Sources</text>
</g>
<g id="clust3" class="cluster">
<title>cluster_adapters</title>
<polygon fill="#8e24aa" stroke="#8e24aa" points="502,-1674.04 502,-2057.88 791,-2057.88 791,-1674.04 502,-1674.04"/>
<text text-anchor="middle" x="646.5" y="-2044.28" font-family="Arial" font-size="12.00">Source Adapters Pattern</text>
</g>
<g id="clust4" class="cluster">
<title>cluster_core</title>
<polygon fill="#1976d2" stroke="#1976d2" points="606,-1115.09 606,-1626.41 800,-1626.41 800,-1115.09 606,-1115.09"/>
<text text-anchor="middle" x="703" y="-1612.81" font-family="Arial" font-size="12.00">Core Platform</text>
</g>
<g id="clust5" class="cluster">
<title>cluster_execution</title>
<polygon fill="#8e24aa" stroke="#8e24aa" points="1574,-549.14 1574,-1012.83 1863,-1012.83 1863,-549.14 1574,-549.14"/>
<text text-anchor="middle" x="1718.5" y="-999.23" font-family="Arial" font-size="12.00">Execution Strategies Pattern</text>
</g>
<g id="clust6" class="cluster">
<title>cluster_event_sources</title>
<polygon fill="#8e24aa" stroke="#8e24aa" points="1134,-808.3 1134,-1319.62 1566,-1319.62 1566,-808.3 1134,-808.3"/>
<text text-anchor="middle" x="1350" y="-1306.02" font-family="Arial" font-size="12.00">Event Source Pattern</text>
</g>
<g id="clust7" class="cluster">
<title>cluster_events</title>
<polygon fill="#1976d2" stroke="#1976d2" points="1100,-22.41 1100,-753.67 1249,-753.67 1249,-22.41 1100,-22.41"/>
<text text-anchor="middle" x="1174.5" y="-740.07" font-family="Arial" font-size="12.00">Event&#45;Driven Processing</text>
</g>
<g id="clust8" class="cluster">
<title>cluster_workers</title>
<polygon fill="#1976d2" stroke="#1976d2" points="365,-801.3 365,-1019.83 800,-1019.83 800,-801.3 365,-801.3"/>
<text text-anchor="middle" x="582.5" y="-1006.23" font-family="Arial" font-size="12.00">Celery Workers</text>
</g>
<g id="clust9" class="cluster">
<title>cluster_ai_adapters</title>
<polygon fill="#8e24aa" stroke="#8e24aa" points="1257,-322.2 1257,-753.67 1566,-753.67 1566,-322.2 1257,-322.2"/>
<text text-anchor="middle" x="1411.5" y="-740.07" font-family="Arial" font-size="12.00">Analysis Adapters Pattern</text>
</g>
<g id="clust10" class="cluster">
<title>cluster_storage</title>
<polygon fill="#1976d2" stroke="#1976d2" points="934,-1115.09 934,-1319.62 1126,-1319.62 1126,-1115.09 934,-1115.09"/>
<text text-anchor="middle" x="1030" y="-1306.02" font-family="Arial" font-size="12.00">Media Storage</text>
</g>
<g id="clust11" class="cluster">
<title>cluster_frontend</title>
<polygon fill="#1976d2" stroke="#1976d2" points="808,-808.3 808,-1326.62 926,-1326.62 926,-808.3 808,-808.3"/>
<text text-anchor="middle" x="867" y="-1313.02" font-family="Arial" font-size="12.00">Frontend</text>
</g>
<g id="clust12" class="cluster">
<title>cluster_cloud</title>
<polygon fill="#1976d2" stroke="#1976d2" points="1483,-22.41 1483,-226.94 1714,-226.94 1714,-22.41 1483,-22.41"/>
<text text-anchor="middle" x="1598.5" y="-213.34" font-family="Arial" font-size="12.00">GCP Services</text>
</g>
<!-- implemented -->
<g id="node1" class="node">
<title>implemented</title>
<polygon fill="#28a745" stroke="transparent" points="228.5,-1944.41 139.5,-1944.41 139.5,-1908.41 228.5,-1908.41 228.5,-1944.41"/>
<text text-anchor="middle" x="184" y="-1923.91" font-family="Arial" font-size="10.00" fill="#ffffff">✅ Implemented</text>
</g>
<!-- planned -->
<g id="node2" class="node">
<title>planned</title>
<polygon fill="#ffc107" stroke="transparent" points="228,-1764.41 160,-1764.41 160,-1728.41 228,-1728.41 228,-1764.41"/>
<text text-anchor="middle" x="194" y="-1743.91" font-family="Arial" font-size="10.00" fill="#212529">⏳ Planned</text>
</g>
<!-- implemented&#45;&gt;planned -->
<!-- code_pattern -->
<g id="node3" class="node">
<title>code_pattern</title>
<polygon fill="#8e24aa" stroke="transparent" points="117,-1944.41 27,-1944.41 27,-1908.41 117,-1908.41 117,-1944.41"/>
<text text-anchor="middle" x="72" y="-1923.91" font-family="Arial" font-size="10.00" fill="#ffffff">📐 Code Pattern</text>
</g>
<!-- service_arch -->
<g id="node4" class="node">
<title>service_arch</title>
<polygon fill="#1976d2" stroke="transparent" points="137.5,-1764.41 16.5,-1764.41 16.5,-1728.41 137.5,-1728.41 137.5,-1764.41"/>
<text text-anchor="middle" x="77" y="-1743.91" font-family="Arial" font-size="10.00" fill="#ffffff">⚡ Service/Architecture</text>
</g>
<!-- code_pattern&#45;&gt;service_arch -->
<!-- webcam -->
<g id="node5" class="node">
<title>webcam</title>
<polygon fill="#28a745" stroke="black" points="307.5,-1944.41 252.5,-1944.41 252.5,-1908.41 307.5,-1908.41 307.5,-1944.41"/>
<text text-anchor="middle" x="280" y="-1923.91" font-family="Arial" font-size="10.00" fill="#ffffff">Webcam</text>
</g>
<!-- webcam_adapter -->
<g id="node9" class="node">
<title>webcam_adapter</title>
<polygon fill="#28a745" stroke="black" points="598.5,-1764.41 509.5,-1764.41 509.5,-1728.41 598.5,-1728.41 598.5,-1764.41"/>
<text text-anchor="middle" x="554" y="-1743.91" font-family="Arial" font-size="10.00" fill="#ffffff">WebcamAdapter</text>
</g>
<!-- webcam&#45;&gt;webcam_adapter -->
<g id="edge3" class="edge">
<title>webcam&#45;&gt;webcam_adapter</title>
<path fill="none" stroke="#2e7d32" d="M301.09,-1908.09C325.95,-1888.02 368.83,-1854.44 408,-1828.91 441.69,-1806.96 481.66,-1784.91 511.26,-1769.28"/>
<polygon fill="#2e7d32" stroke="#2e7d32" points="513.25,-1772.19 520.48,-1764.45 510,-1765.99 513.25,-1772.19"/>
</g>
<!-- rtmp -->
<g id="node6" class="node">
<title>rtmp</title>
<polygon fill="#28a745" stroke="black" points="486,-1944.41 418,-1944.41 418,-1908.41 486,-1908.41 486,-1944.41"/>
<text text-anchor="middle" x="452" y="-1923.91" font-family="Arial" font-size="10.00" fill="#ffffff">RTMP/OBS</text>
</g>
<!-- rtmp_adapter -->
<g id="node10" class="node">
<title>rtmp_adapter</title>
<polygon fill="#28a745" stroke="black" points="783,-1764.41 709,-1764.41 709,-1728.41 783,-1728.41 783,-1764.41"/>
<text text-anchor="middle" x="746" y="-1743.91" font-family="Arial" font-size="10.00" fill="#ffffff">RtmpAdapter</text>
</g>
<!-- rtmp&#45;&gt;rtmp_adapter -->
<g id="edge4" class="edge">
<title>rtmp&#45;&gt;rtmp_adapter</title>
<path fill="none" stroke="#2e7d32" d="M480.19,-1908.35C533.64,-1875.98 649.69,-1805.72 709.19,-1769.7"/>
<polygon fill="#2e7d32" stroke="#2e7d32" points="711.15,-1772.6 717.9,-1764.43 707.53,-1766.61 711.15,-1772.6"/>
</g>
<!-- files -->
<g id="node7" class="node">
<title>files</title>
<polygon fill="#ffc107" stroke="black" points="396,-1944.41 330,-1944.41 330,-1908.41 396,-1908.41 396,-1944.41"/>
<text text-anchor="middle" x="363" y="-1923.91" font-family="Arial" font-size="10.00" fill="#212529">File Upload</text>
</g>
<!-- file_adapter -->
<g id="node11" class="node">
<title>file_adapter</title>
<polygon fill="#ffc107" stroke="black" points="687,-1764.41 621,-1764.41 621,-1728.41 687,-1728.41 687,-1764.41"/>
<text text-anchor="middle" x="654" y="-1743.91" font-family="Arial" font-size="10.00" fill="#212529">FileAdapter</text>
</g>
<!-- files&#45;&gt;file_adapter -->
<g id="edge28" class="edge">
<title>files&#45;&gt;file_adapter</title>
<path fill="none" stroke="#f57f17" stroke-dasharray="5,2" d="M385.67,-1908.1C412.36,-1888.04 458.34,-1854.47 500,-1828.91 536.69,-1806.41 580.16,-1783.75 611.55,-1768.05"/>
<polygon fill="#f57f17" stroke="#f57f17" points="613.49,-1771 620.88,-1763.41 610.37,-1764.73 613.49,-1771"/>
</g>
<!-- base_adapter -->
<g id="node8" class="node">
<title>base_adapter</title>
<polygon fill="#ce93d8" stroke="black" points="706,-1944.41 602,-1944.41 602,-1908.41 706,-1908.41 706,-1944.41"/>
<text text-anchor="middle" x="654" y="-1929.41" font-family="Arial" font-size="10.00">BaseSourceAdapter</text>
<text text-anchor="middle" x="654" y="-1918.41" font-family="Arial" font-size="10.00">(Abstract)</text>
</g>
<!-- base_adapter&#45;&gt;webcam_adapter -->
<g id="edge38" class="edge">
<title>base_adapter&#45;&gt;webcam_adapter</title>
<path fill="none" stroke="gray" stroke-dasharray="1,5" d="M644.41,-1908.35C626.87,-1877.11 589.49,-1810.58 568.71,-1773.59"/>
<polygon fill="gray" stroke="gray" points="571.51,-1771.43 563.56,-1764.43 565.41,-1774.86 571.51,-1771.43"/>
</g>
<!-- base_adapter&#45;&gt;rtmp_adapter -->
<g id="edge39" class="edge">
<title>base_adapter&#45;&gt;rtmp_adapter</title>
<path fill="none" stroke="gray" stroke-dasharray="1,5" d="M662.82,-1908.35C678.96,-1877.11 713.35,-1810.58 732.47,-1773.59"/>
<polygon fill="gray" stroke="gray" points="735.72,-1774.92 737.21,-1764.43 729.5,-1771.71 735.72,-1774.92"/>
</g>
<!-- base_adapter&#45;&gt;file_adapter -->
<g id="edge40" class="edge">
<title>base_adapter&#45;&gt;file_adapter</title>
<path fill="none" stroke="gray" stroke-dasharray="1,5" d="M654,-1908.35C654,-1877.38 654,-1811.71 654,-1774.54"/>
<polygon fill="gray" stroke="gray" points="657.5,-1774.43 654,-1764.43 650.5,-1774.43 657.5,-1774.43"/>
</g>
<!-- django -->
<g id="node12" class="node">
<title>django</title>
<polygon fill="#28a745" stroke="black" points="687.5,-1507.91 620.5,-1507.91 620.5,-1466.91 687.5,-1466.91 687.5,-1507.91"/>
<text text-anchor="middle" x="654" y="-1495.91" font-family="Arial" font-size="10.00" fill="#ffffff">Django API</text>
<text text-anchor="middle" x="654" y="-1484.91" font-family="Arial" font-size="10.00" fill="#ffffff">+ Channels</text>
<text text-anchor="middle" x="654" y="-1473.91" font-family="Arial" font-size="10.00" fill="#ffffff">:8000</text>
</g>
<!-- webcam_adapter&#45;&gt;django -->
<g id="edge5" class="edge">
<title>webcam_adapter&#45;&gt;django</title>
<path fill="none" stroke="#2e7d32" d="M560.72,-1728.15C577.54,-1684.91 621.65,-1571.55 642.62,-1517.67"/>
<polygon fill="#2e7d32" stroke="#2e7d32" points="646,-1518.62 646.37,-1508.03 639.48,-1516.08 646,-1518.62"/>
</g>
<!-- rtmp_adapter&#45;&gt;django -->
<g id="edge6" class="edge">
<title>rtmp_adapter&#45;&gt;django</title>
<path fill="none" stroke="#2e7d32" d="M739.82,-1728.15C724.34,-1684.91 683.76,-1571.55 664.47,-1517.67"/>
<polygon fill="#2e7d32" stroke="#2e7d32" points="667.69,-1516.26 661.02,-1508.03 661.1,-1518.62 667.69,-1516.26"/>
</g>
<!-- file_adapter&#45;&gt;django -->
<g id="edge29" class="edge">
<title>file_adapter&#45;&gt;django</title>
<path fill="none" stroke="#f57f17" stroke-dasharray="5,2" d="M654,-1728.15C654,-1685.09 654,-1572.49 654,-1518.35"/>
<polygon fill="#f57f17" stroke="#f57f17" points="657.5,-1518.03 654,-1508.03 650.5,-1518.03 657.5,-1518.03"/>
</g>
<!-- postgres -->
<g id="node13" class="node">
<title>postgres</title>
<polygon fill="#28a745" stroke="black" points="792,-1206.41 722,-1206.41 722,-1170.41 792,-1170.41 792,-1206.41"/>
<text text-anchor="middle" x="757" y="-1191.41" font-family="Arial" font-size="10.00" fill="#ffffff">PostgreSQL</text>
<text text-anchor="middle" x="757" y="-1180.41" font-family="Arial" font-size="10.00" fill="#ffffff">Database</text>
</g>
<!-- django&#45;&gt;postgres -->
<g id="edge7" class="edge">
<title>django&#45;&gt;postgres</title>
<path fill="none" stroke="#2e7d32" d="M660.92,-1466.47C678.92,-1414.57 727.22,-1275.28 747.66,-1216.34"/>
<polygon fill="#2e7d32" stroke="#2e7d32" points="751.06,-1217.23 751.03,-1206.63 744.45,-1214.93 751.06,-1217.23"/>
</g>
<!-- redis -->
<g id="node14" class="node">
<title>redis</title>
<polygon fill="#28a745" stroke="black" points="700,-1206.41 614,-1206.41 614,-1170.41 700,-1170.41 700,-1206.41"/>
<text text-anchor="middle" x="657" y="-1191.41" font-family="Arial" font-size="10.00" fill="#ffffff">Redis</text>
<text text-anchor="middle" x="657" y="-1180.41" font-family="Arial" font-size="10.00" fill="#ffffff">Cache &amp; Broker</text>
</g>
<!-- django&#45;&gt;redis -->
<g id="edge8" class="edge">
<title>django&#45;&gt;redis</title>
<path fill="none" stroke="#2e7d32" d="M654.2,-1466.47C654.72,-1414.67 656.13,-1275.85 656.72,-1216.71"/>
<polygon fill="#2e7d32" stroke="#2e7d32" points="660.22,-1216.67 656.83,-1206.63 653.23,-1216.59 660.22,-1216.67"/>
</g>
<!-- local_storage -->
<g id="node35" class="node">
<title>local_storage</title>
<polygon fill="#28a745" stroke="black" points="1020,-1206.41 942,-1206.41 942,-1170.41 1020,-1170.41 1020,-1206.41"/>
<text text-anchor="middle" x="981" y="-1191.41" font-family="Arial" font-size="10.00" fill="#ffffff">Local Files</text>
<text text-anchor="middle" x="981" y="-1180.41" font-family="Arial" font-size="10.00" fill="#ffffff">(nginx&#45;served)</text>
</g>
<!-- django&#45;&gt;local_storage -->
<g id="edge9" class="edge">
<title>django&#45;&gt;local_storage</title>
<path fill="none" stroke="#2e7d32" d="M678.88,-1466.81C704.44,-1446.47 745.15,-1413.48 779,-1383.41 848.91,-1321.3 863.66,-1302.8 931,-1237.91 939.1,-1230.11 947.91,-1221.58 955.85,-1213.87"/>
<polygon fill="#2e7d32" stroke="#2e7d32" points="958.71,-1215.98 963.44,-1206.5 953.83,-1210.96 958.71,-1215.98"/>
</g>
<!-- gcs_storage -->
<g id="node36" class="node">
<title>gcs_storage</title>
<polygon fill="#ffc107" stroke="black" points="1118,-1206.41 1042,-1206.41 1042,-1170.41 1118,-1170.41 1118,-1206.41"/>
<text text-anchor="middle" x="1080" y="-1191.41" font-family="Arial" font-size="10.00" fill="#212529">Google Cloud</text>
<text text-anchor="middle" x="1080" y="-1180.41" font-family="Arial" font-size="10.00" fill="#212529">Storage</text>
</g>
<!-- django&#45;&gt;gcs_storage -->
<g id="edge10" class="edge">
<title>django&#45;&gt;gcs_storage</title>
<path fill="none" stroke="#2e7d32" d="M687.53,-1467.36C755.28,-1428.23 912.13,-1334.34 1031,-1237.91 1039.92,-1230.68 1049.05,-1222.05 1056.96,-1214.09"/>
<polygon fill="#2e7d32" stroke="#2e7d32" points="1059.95,-1216.03 1064.42,-1206.43 1054.94,-1211.15 1059.95,-1216.03"/>
</g>
<!-- angular -->
<g id="node37" class="node">
<title>angular</title>
<polygon fill="#28a745" stroke="black" points="902,-1208.91 816,-1208.91 816,-1167.91 902,-1167.91 902,-1208.91"/>
<text text-anchor="middle" x="859" y="-1196.91" font-family="Arial" font-size="10.00" fill="#ffffff">Angular 17 SPA</text>
<text text-anchor="middle" x="859" y="-1185.91" font-family="Arial" font-size="10.00" fill="#ffffff">+ WebSocket</text>
<text text-anchor="middle" x="859" y="-1174.91" font-family="Arial" font-size="10.00" fill="#ffffff">:4200</text>
</g>
<!-- django&#45;&gt;angular -->
<g id="edge25" class="edge">
<title>django&#45;&gt;angular</title>
<path fill="none" stroke="#2e7d32" d="M667.48,-1466.69C683.88,-1442.73 712.42,-1401.07 737,-1365.41 773.19,-1312.93 815.63,-1251.8 839.72,-1217.14"/>
<polygon fill="#2e7d32" stroke="#2e7d32" points="842.59,-1219.13 845.43,-1208.93 836.85,-1215.14 842.59,-1219.13"/>
<text text-anchor="middle" x="757.5" y="-1377.01" font-family="Arial" font-size="8.00">WebSocket</text>
<text text-anchor="middle" x="757.5" y="-1368.01" font-family="Arial" font-size="8.00">API</text>
</g>
<!-- logo_worker -->
<g id="node27" class="node">
<title>logo_worker</title>
<polygon fill="#28a745" stroke="black" points="456.5,-901.91 373.5,-901.91 373.5,-860.91 456.5,-860.91 456.5,-901.91"/>
<text text-anchor="middle" x="415" y="-889.91" font-family="Arial" font-size="10.00" fill="#ffffff">Logo Detection</text>
<text text-anchor="middle" x="415" y="-878.91" font-family="Arial" font-size="10.00" fill="#ffffff">Worker</text>
<text text-anchor="middle" x="415" y="-867.91" font-family="Arial" font-size="10.00" fill="#ffffff">(logo_queue)</text>
</g>
<!-- redis&#45;&gt;logo_worker -->
<g id="edge19" class="edge">
<title>redis&#45;&gt;logo_worker</title>
<path fill="none" stroke="#2e7d32" d="M643.3,-1170.14C603.28,-1119.71 486.35,-972.34 437.19,-910.38"/>
<polygon fill="#2e7d32" stroke="#2e7d32" points="439.67,-907.88 430.71,-902.22 434.19,-912.23 439.67,-907.88"/>
</g>
<!-- visual_worker -->
<g id="node28" class="node">
<title>visual_worker</title>
<polygon fill="#ffc107" stroke="black" points="569.5,-901.91 478.5,-901.91 478.5,-860.91 569.5,-860.91 569.5,-901.91"/>
<text text-anchor="middle" x="524" y="-889.91" font-family="Arial" font-size="10.00" fill="#212529">Visual Properties</text>
<text text-anchor="middle" x="524" y="-878.91" font-family="Arial" font-size="10.00" fill="#212529">Worker</text>
<text text-anchor="middle" x="524" y="-867.91" font-family="Arial" font-size="10.00" fill="#212529">(visual_queue)</text>
</g>
<!-- redis&#45;&gt;visual_worker -->
<g id="edge30" class="edge">
<title>redis&#45;&gt;visual_worker</title>
<path fill="none" stroke="#f57f17" stroke-dasharray="5,2" d="M649.47,-1170.14C627.61,-1120.02 564,-974.15 536.69,-911.53"/>
<polygon fill="#f57f17" stroke="#f57f17" points="539.84,-909.99 532.64,-902.22 533.42,-912.78 539.84,-909.99"/>
</g>
<!-- audio_worker -->
<g id="node29" class="node">
<title>audio_worker</title>
<polygon fill="#ffc107" stroke="black" points="791.5,-901.91 704.5,-901.91 704.5,-860.91 791.5,-860.91 791.5,-901.91"/>
<text text-anchor="middle" x="748" y="-889.91" font-family="Arial" font-size="10.00" fill="#212529">Audio Transcript</text>
<text text-anchor="middle" x="748" y="-878.91" font-family="Arial" font-size="10.00" fill="#212529">Worker</text>
<text text-anchor="middle" x="748" y="-867.91" font-family="Arial" font-size="10.00" fill="#212529">(audio_queue)</text>
</g>
<!-- redis&#45;&gt;audio_worker -->
<g id="edge31" class="edge">
<title>redis&#45;&gt;audio_worker</title>
<path fill="none" stroke="#f57f17" stroke-dasharray="5,2" d="M662.15,-1170.14C677.08,-1120.13 720.45,-974.75 739.2,-911.91"/>
<polygon fill="#f57f17" stroke="#f57f17" points="742.59,-912.8 742.09,-902.22 735.88,-910.8 742.59,-912.8"/>
</g>
<!-- text_worker -->
<g id="node30" class="node">
<title>text_worker</title>
<polygon fill="#ffc107" stroke="black" points="682,-901.91 592,-901.91 592,-860.91 682,-860.91 682,-901.91"/>
<text text-anchor="middle" x="637" y="-889.91" font-family="Arial" font-size="10.00" fill="#212529">Text Recognition</text>
<text text-anchor="middle" x="637" y="-878.91" font-family="Arial" font-size="10.00" fill="#212529">Worker</text>
<text text-anchor="middle" x="637" y="-867.91" font-family="Arial" font-size="10.00" fill="#212529">(text_queue)</text>
</g>
<!-- redis&#45;&gt;text_worker -->
<g id="edge32" class="edge">
<title>redis&#45;&gt;text_worker</title>
<path fill="none" stroke="#f57f17" stroke-dasharray="5,2" d="M655.87,-1170.14C652.59,-1120.23 643.09,-975.35 638.96,-912.3"/>
<polygon fill="#f57f17" stroke="#f57f17" points="642.45,-911.97 638.3,-902.22 635.46,-912.43 642.45,-911.97"/>
</g>
<!-- nginx -->
<g id="node15" class="node">
<title>nginx</title>
<polygon fill="#28a745" stroke="black" points="792,-1507.91 710,-1507.91 710,-1466.91 792,-1466.91 792,-1507.91"/>
<text text-anchor="middle" x="751" y="-1495.91" font-family="Arial" font-size="10.00" fill="#ffffff">NGINX</text>
<text text-anchor="middle" x="751" y="-1484.91" font-family="Arial" font-size="10.00" fill="#ffffff">Reverse Proxy</text>
<text text-anchor="middle" x="751" y="-1473.91" font-family="Arial" font-size="10.00" fill="#ffffff">:80</text>
</g>
<!-- nginx&#45;&gt;angular -->
<g id="edge27" class="edge">
<title>nginx&#45;&gt;angular</title>
<path fill="none" stroke="#2e7d32" d="M758.25,-1466.47C776.85,-1415.32 826.31,-1279.3 848.26,-1218.96"/>
<polygon fill="#2e7d32" stroke="#2e7d32" points="851.65,-1219.87 851.78,-1209.28 845.07,-1217.48 851.65,-1219.87"/>
</g>
<!-- base_strategy -->
<g id="node16" class="node">
<title>base_strategy</title>
<polygon fill="#ce93d8" stroke="black" points="1777.5,-899.41 1658.5,-899.41 1658.5,-863.41 1777.5,-863.41 1777.5,-899.41"/>
<text text-anchor="middle" x="1718" y="-884.41" font-family="Arial" font-size="10.00">BaseExecutionStrategy</text>
<text text-anchor="middle" x="1718" y="-873.41" font-family="Arial" font-size="10.00">(Abstract)</text>
</g>
<!-- local_strategy -->
<g id="node17" class="node">
<title>local_strategy</title>
<polygon fill="#28a745" stroke="black" points="1659.5,-640.41 1582.5,-640.41 1582.5,-604.41 1659.5,-604.41 1659.5,-640.41"/>
<text text-anchor="middle" x="1621" y="-619.91" font-family="Arial" font-size="10.00" fill="#ffffff">LocalStrategy</text>
</g>
<!-- base_strategy&#45;&gt;local_strategy -->
<g id="edge41" class="edge">
<title>base_strategy&#45;&gt;local_strategy</title>
<path fill="none" stroke="gray" stroke-dasharray="1,5" d="M1711.48,-863.15C1694.88,-819.17 1650.91,-702.65 1631.02,-649.96"/>
<polygon fill="gray" stroke="gray" points="1634.29,-648.72 1627.49,-640.6 1627.74,-651.19 1634.29,-648.72"/>
</g>
<!-- lan_strategy -->
<g id="node18" class="node">
<title>lan_strategy</title>
<polygon fill="#ffc107" stroke="black" points="1754.5,-640.41 1681.5,-640.41 1681.5,-604.41 1754.5,-604.41 1754.5,-640.41"/>
<text text-anchor="middle" x="1718" y="-619.91" font-family="Arial" font-size="10.00" fill="#212529">LANStrategy</text>
</g>
<!-- base_strategy&#45;&gt;lan_strategy -->
<g id="edge42" class="edge">
<title>base_strategy&#45;&gt;lan_strategy</title>
<path fill="none" stroke="gray" stroke-dasharray="1,5" d="M1718,-863.15C1718,-819.35 1718,-703.62 1718,-650.62"/>
<polygon fill="gray" stroke="gray" points="1721.5,-650.6 1718,-640.6 1714.5,-650.6 1721.5,-650.6"/>
</g>
<!-- cloud_strategy -->
<g id="node19" class="node">
<title>cloud_strategy</title>
<polygon fill="#ffc107" stroke="black" points="1855.5,-640.41 1776.5,-640.41 1776.5,-604.41 1855.5,-604.41 1855.5,-640.41"/>
<text text-anchor="middle" x="1816" y="-619.91" font-family="Arial" font-size="10.00" fill="#212529">CloudStrategy</text>
</g>
<!-- base_strategy&#45;&gt;cloud_strategy -->
<g id="edge43" class="edge">
<title>base_strategy&#45;&gt;cloud_strategy</title>
<path fill="none" stroke="gray" stroke-dasharray="1,5" d="M1724.58,-863.15C1741.35,-819.17 1785.79,-702.65 1805.88,-649.96"/>
<polygon fill="gray" stroke="gray" points="1809.15,-651.19 1809.45,-640.6 1802.61,-648.7 1809.15,-651.19"/>
</g>
<!-- clip_adapter -->
<g id="node32" class="node">
<title>clip_adapter</title>
<polygon fill="#28a745" stroke="black" points="1337,-413.41 1265,-413.41 1265,-377.41 1337,-377.41 1337,-413.41"/>
<text text-anchor="middle" x="1301" y="-398.41" font-family="Arial" font-size="10.00" fill="#ffffff">CLIPAdapter</text>
<text text-anchor="middle" x="1301" y="-387.41" font-family="Arial" font-size="10.00" fill="#ffffff">(Local)</text>
</g>
<!-- local_strategy&#45;&gt;clip_adapter -->
<g id="edge21" class="edge">
<title>local_strategy&#45;&gt;clip_adapter</title>
<path fill="none" stroke="#2e7d32" d="M1596.69,-604.32C1539.85,-564.36 1398.25,-464.8 1333.84,-419.5"/>
<polygon fill="#2e7d32" stroke="#2e7d32" points="1335.47,-416.37 1325.28,-413.48 1331.44,-422.1 1335.47,-416.37"/>
</g>
<!-- gcp_vision -->
<g id="node33" class="node">
<title>gcp_vision</title>
<polygon fill="#ffc107" stroke="black" points="1458.5,-413.41 1359.5,-413.41 1359.5,-377.41 1458.5,-377.41 1458.5,-413.41"/>
<text text-anchor="middle" x="1409" y="-398.41" font-family="Arial" font-size="10.00" fill="#212529">GCPVisionAdapter</text>
<text text-anchor="middle" x="1409" y="-387.41" font-family="Arial" font-size="10.00" fill="#212529">(Cloud)</text>
</g>
<!-- local_strategy&#45;&gt;gcp_vision -->
<g id="edge22" class="edge">
<title>local_strategy&#45;&gt;gcp_vision</title>
<path fill="none" stroke="#2e7d32" d="M1608.7,-604.39C1590.04,-578.99 1552.92,-530.11 1517,-492.41 1491.88,-466.05 1460.52,-438.72 1438.07,-419.99"/>
<polygon fill="#2e7d32" stroke="#2e7d32" points="1440.17,-417.18 1430.23,-413.5 1435.7,-422.57 1440.17,-417.18"/>
</g>
<!-- yolo_adapter -->
<g id="node34" class="node">
<title>yolo_adapter</title>
<polygon fill="#ffc107" stroke="black" points="1557.5,-413.41 1480.5,-413.41 1480.5,-377.41 1557.5,-377.41 1557.5,-413.41"/>
<text text-anchor="middle" x="1519" y="-398.41" font-family="Arial" font-size="10.00" fill="#212529">YOLOAdapter</text>
<text text-anchor="middle" x="1519" y="-387.41" font-family="Arial" font-size="10.00" fill="#212529">(Planned)</text>
</g>
<!-- lan_strategy&#45;&gt;yolo_adapter -->
<g id="edge37" class="edge">
<title>lan_strategy&#45;&gt;yolo_adapter</title>
<path fill="none" stroke="#f57f17" stroke-dasharray="5,2" d="M1702.72,-604.13C1667.69,-564.53 1581.5,-467.08 1540.87,-421.14"/>
<polygon fill="#f57f17" stroke="#f57f17" points="1543.31,-418.62 1534.06,-413.45 1538.07,-423.26 1543.31,-418.62"/>
</g>
<!-- speech_api -->
<g id="node40" class="node">
<title>speech_api</title>
<polygon fill="#ffc107" stroke="black" points="1705.5,-113.41 1604.5,-113.41 1604.5,-77.41 1705.5,-77.41 1705.5,-113.41"/>
<text text-anchor="middle" x="1655" y="-98.41" font-family="Arial" font-size="10.00" fill="#212529">Speech&#45;to&#45;Text API</text>
<text text-anchor="middle" x="1655" y="-87.41" font-family="Arial" font-size="10.00" fill="#212529">(Audio Transcript)</text>
</g>
<!-- cloud_strategy&#45;&gt;speech_api -->
<g id="edge36" class="edge">
<title>cloud_strategy&#45;&gt;speech_api</title>
<path fill="none" stroke="#f57f17" stroke-dasharray="5,2" d="M1810.73,-604.24C1787.25,-527.67 1691.98,-216.99 1663.24,-123.29"/>
<polygon fill="#f57f17" stroke="#f57f17" points="1666.5,-121.99 1660.23,-113.45 1659.81,-124.04 1666.5,-121.99"/>
</g>
<!-- base_event_source -->
<g id="node20" class="node">
<title>base_event_source</title>
<polygon fill="#ce93d8" stroke="black" points="1412,-1206.41 1300,-1206.41 1300,-1170.41 1412,-1170.41 1412,-1206.41"/>
<text text-anchor="middle" x="1356" y="-1191.41" font-family="Arial" font-size="10.00">SegmentEventSource</text>
<text text-anchor="middle" x="1356" y="-1180.41" font-family="Arial" font-size="10.00">(Abstract)</text>
</g>
<!-- file_watcher_source -->
<g id="node21" class="node">
<title>file_watcher_source</title>
<polygon fill="#28a745" stroke="black" points="1267.5,-899.41 1142.5,-899.41 1142.5,-863.41 1267.5,-863.41 1267.5,-899.41"/>
<text text-anchor="middle" x="1205" y="-884.41" font-family="Arial" font-size="10.00" fill="#ffffff">FileWatcherEventSource</text>
<text text-anchor="middle" x="1205" y="-873.41" font-family="Arial" font-size="10.00" fill="#ffffff">(Local/LAN)</text>
</g>
<!-- base_event_source&#45;&gt;file_watcher_source -->
<g id="edge47" class="edge">
<title>base_event_source&#45;&gt;file_watcher_source</title>
<path fill="none" stroke="gray" stroke-dasharray="1,5" d="M1347.45,-1170.14C1322.22,-1119.18 1247.99,-969.25 1217.89,-908.46"/>
<polygon fill="gray" stroke="gray" points="1221.03,-906.91 1213.46,-899.5 1214.76,-910.01 1221.03,-906.91"/>
</g>
<!-- cloud_storage_source -->
<g id="node22" class="node">
<title>cloud_storage_source</title>
<polygon fill="#ffc107" stroke="black" points="1422,-899.41 1290,-899.41 1290,-863.41 1422,-863.41 1422,-899.41"/>
<text text-anchor="middle" x="1356" y="-884.41" font-family="Arial" font-size="10.00" fill="#212529">CloudStorageEventSource</text>
<text text-anchor="middle" x="1356" y="-873.41" font-family="Arial" font-size="10.00" fill="#212529">(GCS Pub/Sub)</text>
</g>
<!-- base_event_source&#45;&gt;cloud_storage_source -->
<g id="edge48" class="edge">
<title>base_event_source&#45;&gt;cloud_storage_source</title>
<path fill="none" stroke="gray" stroke-dasharray="1,5" d="M1356,-1170.14C1356,-1119.5 1356,-971.09 1356,-909.59"/>
<polygon fill="gray" stroke="gray" points="1359.5,-909.5 1356,-899.5 1352.5,-909.5 1359.5,-909.5"/>
</g>
<!-- webhook_source -->
<g id="node23" class="node">
<title>webhook_source</title>
<polygon fill="#ffc107" stroke="black" points="1557.5,-899.41 1444.5,-899.41 1444.5,-863.41 1557.5,-863.41 1557.5,-899.41"/>
<text text-anchor="middle" x="1501" y="-884.41" font-family="Arial" font-size="10.00" fill="#212529">WebhookEventSource</text>
<text text-anchor="middle" x="1501" y="-873.41" font-family="Arial" font-size="10.00" fill="#212529">(External)</text>
</g>
<!-- base_event_source&#45;&gt;webhook_source -->
<g id="edge49" class="edge">
<title>base_event_source&#45;&gt;webhook_source</title>
<path fill="none" stroke="gray" stroke-dasharray="1,5" d="M1364.21,-1170.14C1388.39,-1119.29 1459.43,-969.86 1488.44,-908.83"/>
<polygon fill="gray" stroke="gray" points="1491.75,-910.03 1492.88,-899.5 1485.42,-907.03 1491.75,-910.03"/>
</g>
<!-- event_source_manager -->
<g id="node24" class="node">
<title>event_source_manager</title>
<polygon fill="#28a745" stroke="black" points="1241,-640.41 1131,-640.41 1131,-604.41 1241,-604.41 1241,-640.41"/>
<text text-anchor="middle" x="1186" y="-625.41" font-family="Arial" font-size="10.00" fill="#ffffff">EventSourceManager</text>
<text text-anchor="middle" x="1186" y="-614.41" font-family="Arial" font-size="10.00" fill="#ffffff">(Environment&#45;based)</text>
</g>
<!-- file_watcher_source&#45;&gt;event_source_manager -->
<g id="edge13" class="edge">
<title>file_watcher_source&#45;&gt;event_source_manager</title>
<path fill="none" stroke="#2e7d32" d="M1203.72,-863.15C1200.49,-819.35 1191.93,-703.62 1188.01,-650.62"/>
<polygon fill="#2e7d32" stroke="#2e7d32" points="1191.5,-650.32 1187.27,-640.6 1184.52,-650.83 1191.5,-650.32"/>
</g>
<!-- cloud_storage_source&#45;&gt;event_source_manager -->
<g id="edge14" class="edge">
<title>cloud_storage_source&#45;&gt;event_source_manager</title>
<path fill="none" stroke="#2e7d32" d="M1344.58,-863.15C1315.31,-818.89 1237.45,-701.19 1202.91,-648.98"/>
<polygon fill="#2e7d32" stroke="#2e7d32" points="1205.8,-647.01 1197.37,-640.6 1199.97,-650.87 1205.8,-647.01"/>
</g>
<!-- webhook_source&#45;&gt;event_source_manager -->
<g id="edge15" class="edge">
<title>webhook_source&#45;&gt;event_source_manager</title>
<path fill="none" stroke="#2e7d32" d="M1479.84,-863.15C1424.92,-818.35 1277.74,-698.27 1214.99,-647.07"/>
<polygon fill="#2e7d32" stroke="#2e7d32" points="1217.03,-644.21 1207.07,-640.6 1212.6,-649.63 1217.03,-644.21"/>
</g>
<!-- redis_events -->
<g id="node25" class="node">
<title>redis_events</title>
<polygon fill="#28a745" stroke="black" points="1231,-413.41 1129,-413.41 1129,-377.41 1231,-377.41 1231,-413.41"/>
<text text-anchor="middle" x="1180" y="-398.41" font-family="Arial" font-size="10.00" fill="#ffffff">Redis Event Queue</text>
<text text-anchor="middle" x="1180" y="-387.41" font-family="Arial" font-size="10.00" fill="#ffffff">(segment_events)</text>
</g>
<!-- event_source_manager&#45;&gt;redis_events -->
<g id="edge16" class="edge">
<title>event_source_manager&#45;&gt;redis_events</title>
<path fill="none" stroke="#2e7d32" d="M1185.54,-604.13C1184.5,-565.18 1181.97,-470.29 1180.72,-423.47"/>
<polygon fill="#2e7d32" stroke="#2e7d32" points="1184.22,-423.35 1180.45,-413.45 1177.22,-423.54 1184.22,-423.35"/>
<text text-anchor="middle" x="1200" y="-504.01" font-family="Arial" font-size="8.00">publishes</text>
<text text-anchor="middle" x="1200" y="-495.01" font-family="Arial" font-size="8.00">events</text>
</g>
<!-- event_processor -->
<g id="node26" class="node">
<title>event_processor</title>
<polygon fill="#28a745" stroke="black" points="1215,-113.41 1121,-113.41 1121,-77.41 1215,-77.41 1215,-113.41"/>
<text text-anchor="middle" x="1168" y="-98.41" font-family="Arial" font-size="10.00" fill="#ffffff">Event Processor</text>
<text text-anchor="middle" x="1168" y="-87.41" font-family="Arial" font-size="10.00" fill="#ffffff">(triggers analysis)</text>
</g>
<!-- redis_events&#45;&gt;event_processor -->
<g id="edge17" class="edge">
<title>redis_events&#45;&gt;event_processor</title>
<path fill="none" stroke="#2e7d32" d="M1179.3,-377.1C1177.31,-327.52 1171.55,-184.65 1169.11,-124.08"/>
<polygon fill="#2e7d32" stroke="#2e7d32" points="1172.6,-123.62 1168.7,-113.77 1165.6,-123.9 1172.6,-123.62"/>
<text text-anchor="middle" x="1193.5" y="-277.01" font-family="Arial" font-size="8.00">consumes</text>
<text text-anchor="middle" x="1193.5" y="-268.01" font-family="Arial" font-size="8.00">events</text>
</g>
<!-- event_processor&#45;&gt;logo_worker -->
<g id="edge18" class="edge">
<title>event_processor&#45;&gt;logo_worker</title>
<path fill="none" stroke="#2e7d32" d="M1151.39,-113.71C1054.28,-214.82 560.34,-729.09 440.99,-853.36"/>
<polygon fill="#2e7d32" stroke="#2e7d32" points="438.39,-851.01 433.99,-860.64 443.44,-855.85 438.39,-851.01"/>
<text text-anchor="middle" x="801" y="-504.01" font-family="Arial" font-size="8.00">triggers</text>
<text text-anchor="middle" x="801" y="-495.01" font-family="Arial" font-size="8.00">analysis</text>
</g>
<!-- logo_worker&#45;&gt;django -->
<g id="edge24" class="edge">
<title>logo_worker&#45;&gt;django</title>
<path fill="none" stroke="#2e7d32" d="M422.76,-902.02C457.7,-990.34 600.65,-1351.58 642.46,-1457.25"/>
<polygon fill="#2e7d32" stroke="#2e7d32" points="639.25,-1458.65 646.18,-1466.66 645.76,-1456.07 639.25,-1458.65"/>
<text text-anchor="middle" x="568" y="-1191.01" font-family="Arial" font-size="8.00">analysis</text>
<text text-anchor="middle" x="568" y="-1182.01" font-family="Arial" font-size="8.00">results</text>
</g>
<!-- logo_worker&#45;&gt;local_strategy -->
<g id="edge20" class="edge">
<title>logo_worker&#45;&gt;local_strategy</title>
<path fill="none" stroke="#2e7d32" d="M448.15,-860.91C454.57,-857.81 461.36,-854.95 468,-852.91 943.1,-707.13 1131.75,-901.86 1571,-669.41 1581.38,-663.92 1591.24,-655.75 1599.43,-647.81"/>
<polygon fill="#2e7d32" stroke="#2e7d32" points="1601.93,-650.25 1606.44,-640.66 1596.93,-645.35 1601.93,-650.25"/>
</g>
<!-- visual_worker&#45;&gt;lan_strategy -->
<g id="edge33" class="edge">
<title>visual_worker&#45;&gt;lan_strategy</title>
<path fill="none" stroke="#f57f17" stroke-dasharray="5,2" d="M559.74,-860.82C566.63,-857.72 573.91,-854.89 581,-852.91 918.99,-758.53 1024.46,-854.14 1367,-777.91 1507.03,-746.75 1549.36,-745.46 1671,-669.41 1680.29,-663.6 1689.23,-655.68 1696.76,-648.05"/>
<polygon fill="#f57f17" stroke="#f57f17" points="1699.47,-650.28 1703.79,-640.6 1694.38,-645.47 1699.47,-650.28"/>
</g>
<!-- audio_worker&#45;&gt;cloud_strategy -->
<g id="edge34" class="edge">
<title>audio_worker&#45;&gt;cloud_strategy</title>
<path fill="none" stroke="#f57f17" stroke-dasharray="5,2" d="M782.76,-860.78C789.32,-857.73 796.25,-854.92 803,-852.91 1081.29,-770.06 1168.88,-842.38 1452,-777.91 1595.97,-745.13 1639.22,-745.1 1766,-669.41 1775.72,-663.61 1785.18,-655.69 1793.21,-648.06"/>
<polygon fill="#f57f17" stroke="#f57f17" points="1796.09,-650.14 1800.72,-640.61 1791.16,-645.17 1796.09,-650.14"/>
</g>
<!-- text_worker&#45;&gt;cloud_strategy -->
<g id="edge35" class="edge">
<title>text_worker&#45;&gt;cloud_strategy</title>
<path fill="none" stroke="#f57f17" stroke-dasharray="5,2" d="M672.75,-860.87C679.64,-857.77 686.92,-854.92 694,-852.91 1003.5,-765.04 1098.77,-842.27 1414,-777.91 1574.4,-745.17 1624.04,-750.95 1766,-669.41 1775.82,-663.77 1785.31,-655.9 1793.33,-648.25"/>
<polygon fill="#f57f17" stroke="#f57f17" points="1796.21,-650.31 1800.82,-640.77 1791.27,-645.36 1796.21,-650.31"/>
</g>
<!-- base_ai -->
<g id="node31" class="node">
<title>base_ai</title>
<polygon fill="#ce93d8" stroke="black" points="1455,-640.41 1363,-640.41 1363,-604.41 1455,-604.41 1455,-640.41"/>
<text text-anchor="middle" x="1409" y="-625.41" font-family="Arial" font-size="10.00">DetectionAdapter</text>
<text text-anchor="middle" x="1409" y="-614.41" font-family="Arial" font-size="10.00">(Abstract)</text>
</g>
<!-- base_ai&#45;&gt;clip_adapter -->
<g id="edge44" class="edge">
<title>base_ai&#45;&gt;clip_adapter</title>
<path fill="none" stroke="gray" stroke-dasharray="1,5" d="M1400.7,-604.13C1381.89,-564.94 1335.89,-469.09 1313.56,-422.58"/>
<polygon fill="gray" stroke="gray" points="1316.66,-420.95 1309.18,-413.45 1310.35,-423.98 1316.66,-420.95"/>
</g>
<!-- base_ai&#45;&gt;gcp_vision -->
<g id="edge45" class="edge">
<title>base_ai&#45;&gt;gcp_vision</title>
<path fill="none" stroke="gray" stroke-dasharray="1,5" d="M1409,-604.13C1409,-565.18 1409,-470.29 1409,-423.47"/>
<polygon fill="gray" stroke="gray" points="1412.5,-423.45 1409,-413.45 1405.5,-423.45 1412.5,-423.45"/>
</g>
<!-- base_ai&#45;&gt;yolo_adapter -->
<g id="edge46" class="edge">
<title>base_ai&#45;&gt;yolo_adapter</title>
<path fill="none" stroke="gray" stroke-dasharray="1,5" d="M1417.45,-604.13C1436.61,-564.94 1483.47,-469.09 1506.21,-422.58"/>
<polygon fill="gray" stroke="gray" points="1509.43,-423.97 1510.67,-413.45 1503.14,-420.89 1509.43,-423.97"/>
</g>
<!-- vision_api -->
<g id="node39" class="node">
<title>vision_api</title>
<polygon fill="#ffc107" stroke="black" points="1582.5,-113.41 1491.5,-113.41 1491.5,-77.41 1582.5,-77.41 1582.5,-113.41"/>
<text text-anchor="middle" x="1537" y="-98.41" font-family="Arial" font-size="10.00" fill="#212529">Cloud Vision API</text>
<text text-anchor="middle" x="1537" y="-87.41" font-family="Arial" font-size="10.00" fill="#212529">(Logo Detection)</text>
</g>
<!-- gcp_vision&#45;&gt;vision_api -->
<g id="edge23" class="edge">
<title>gcp_vision&#45;&gt;vision_api</title>
<path fill="none" stroke="#2e7d32" d="M1416.44,-377.1C1437.87,-327.21 1499.87,-182.87 1525.6,-122.96"/>
<polygon fill="#2e7d32" stroke="#2e7d32" points="1528.81,-124.34 1529.54,-113.77 1522.38,-121.58 1528.81,-124.34"/>
</g>
<!-- local_storage&#45;&gt;file_watcher_source -->
<g id="edge11" class="edge">
<title>local_storage&#45;&gt;file_watcher_source</title>
<path fill="none" stroke="#2e7d32" d="M987.69,-1170.31C998.05,-1144.8 1019.48,-1095.78 1045,-1058.41 1085.53,-999.06 1144.91,-939.06 1178.77,-906.73"/>
<polygon fill="#2e7d32" stroke="#2e7d32" points="1181.55,-908.92 1186.4,-899.5 1176.73,-903.84 1181.55,-908.92"/>
<text text-anchor="middle" x="1071.5" y="-1070.01" font-family="Arial" font-size="8.00">monitors</text>
<text text-anchor="middle" x="1071.5" y="-1061.01" font-family="Arial" font-size="8.00">HLS segments</text>
</g>
<!-- gcs_storage&#45;&gt;cloud_storage_source -->
<g id="edge12" class="edge">
<title>gcs_storage&#45;&gt;cloud_storage_source</title>
<path fill="none" stroke="#2e7d32" d="M1095.63,-1170.14C1142.12,-1118.77 1279.66,-966.77 1333.77,-906.98"/>
<polygon fill="#2e7d32" stroke="#2e7d32" points="1336.43,-909.26 1340.54,-899.5 1331.24,-904.56 1336.43,-909.26"/>
<text text-anchor="middle" x="1207" y="-1070.01" font-family="Arial" font-size="8.00">storage</text>
<text text-anchor="middle" x="1207" y="-1061.01" font-family="Arial" font-size="8.00">events</text>
</g>
<!-- hls_player -->
<g id="node38" class="node">
<title>hls_player</title>
<polygon fill="#28a745" stroke="black" points="917.5,-899.41 816.5,-899.41 816.5,-863.41 917.5,-863.41 917.5,-899.41"/>
<text text-anchor="middle" x="867" y="-884.41" font-family="Arial" font-size="10.00" fill="#ffffff">HLS.js Player</text>
<text text-anchor="middle" x="867" y="-873.41" font-family="Arial" font-size="10.00" fill="#ffffff">+ Canvas Overlays</text>
</g>
<!-- angular&#45;&gt;hls_player -->
<g id="edge26" class="edge">
<title>angular&#45;&gt;hls_player</title>
<path fill="none" stroke="#2e7d32" d="M859.51,-1167.87C860.89,-1115.27 864.69,-970.56 866.28,-909.82"/>
<polygon fill="#2e7d32" stroke="#2e7d32" points="869.79,-909.59 866.55,-899.5 862.79,-909.4 869.79,-909.59"/>
</g>
</g>
</svg>