A viewer for AtmosphereConf 2026 talks with fixed routes you can link to
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Fix deny list: make valid JSON, keep only non-talk entries

The comment-stripping regex was matching // inside at:// URIs,
silently corrupting every entry so the deny list filtered nothing.
Removed comments from the JSON file and simplified parsing to plain
JSON.parse. Also trimmed the list to only non-talk entries (starting
soon, lunch, join us, duplicates) — all actual talks are now included.

Reduced audio ready-wait timeout from 3s to 1s.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

+28 -130
+21 -122
public/denied-vods.json
··· 1 1 [ 2 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3miah6keewv2n", // follow @stream.place for VODs (400s) 3 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mi7sb5disa2y", // IRL only / No Stream (1100s) 4 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mi7jx4xi2g25", // ATmosphereConf Starting Soon (1479s) 5 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mi7jnnnh7i2h", // ATmosphereConf Starting Soon! (36s) 6 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mi7isob4ae2a", // ATmosphereConf starting soon! (706s) 7 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mi5dvnqcf72u", // lunch (4334s) 8 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mi5dv7xthz26", // lunch (4307s) 9 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mi5csvtgdg22", // Lunch Break (5488s) 10 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mi2ubr4zq72d", // lunch break 1 hour (2766s) 11 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3miafywhnca2r", // Please join us in stream 1 for closing remarks (448s) 12 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3miafuv53nh2z", // Please join us in stream 1 for closing remarks (280s) 13 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mi5xky7ogz23", // Join us tomorrow! (550s) 14 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mi5wqwpqx72z", // Join us tomorrow! (162s) 15 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mi5wj4mc6t2e", // Join us tomorrow! (367s) 16 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mi5n54d6r42u", // join us in https://stream.place/stream1.atmosphereconf.org for 2026 Atmosphere Report (3174s) 17 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mi5mvmovsn2i", // join us in https://stream.place/stream1.atmosphereconf.org for 2026 Atmosphere Report (3411s) 18 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3miafr5amxa2m", // closing remarks (1506s) 19 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3miaef2b4mh2h", // Rewilding the internet with ATProto (1452s) 20 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3miaec7exqi25", // An artist dreaming in the Atmosphere: visions about community, sustainability and creativity (1683s) 21 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3miadvkvhfv2h", // DID:PLC War Games (2248s) 22 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3miadd43al32c", // Matadata! Publishing scientific data straight to AT (619s) 23 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3miadb23fme2a", // Wherever You Get Your Podcasts: Interoperability in the Atmosphere (1192s) 24 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3miacona6fc2e", // AT Transparency Logs: accountable record collections (679s) 25 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3miacmwnd2z2z", // Jacquard Magic: how to make atproto actually easy with Rust (1782s) 26 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3miacmdq4sm2a", // How to use Bluesky to easily and securely preview a software product to users. (678s) 27 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3miac5ez6a22r", // Skylimit: A curating web client with fine-grained controls to mimic the newspaper experience (565s) 28 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3miac3urhgt23", // Using GraphQL to build with ATProto (540s) 29 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3miac22soys22", // Affordances of the Atmosphere (588s) 30 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3miabh2g67c2c", // Scaling the Atmosphere (718s) 31 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3miabfvrtei26", // Abstracting the AppView (721s) 32 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mia7iun75l2x", // Keywords vs Embeddings (2080s) 33 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mia7dt6fnp2m", // ATProto design philosophy behind BookHive (2191s) 34 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mia74qg3622a", // Building Bridgy, Not Walls (3112s) 35 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mia5q5vu4q2h", // WebTiles Showcase (1902s) 36 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mia5mbp4tf22", // From Toilets to Moths: The Future of Social Media is Weird and Not For Everyone (1854s) 37 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mia5khdija2h", // Protocol Governance & Hard Decentralization (1668s) 38 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mia3vqrg4r23", // Data Sovereignty for Games (and Everything Else): Building Decentralized Industry Infrastructure on ATProto (1748s) 39 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mia3vm5oyd2u", // Coop: Open source Trust & Safety infrastructure for all (1950s) 40 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mia3svkvjw22", // furryli.st — Building Communities Without Landlords From the Protocol Up (1916s) 41 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mia26ffz2j2c", // Two Years of Skywatch: Lessons Learned for Community Moderation (1854s) 42 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mi7zxhekcu2d", // Building decentralized AI on atproto (1992s) 43 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mi7ztge2sf2h", // Designing for the social web (2217s) 44 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mi7tqadgv22d", // Social Components (6533s) 45 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mi7tcodsqu2t", // Creating a Safer Web: Blacksky's Moderation Tool (7351s) 46 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mi7tbwgymp25", // Compete or kill Cooperate and Succeed! (7166s) 47 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mi7rvqdpj722", // A Fireside Chat on Resonant Computing: Why we wrote the manifesto and where we go from here (1944s) 48 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mi7rpxijg725", // Community privacy in a decentralized network (1647s) 49 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mi7q5mjlbe2c", // Blousques: Case Study on the Challenges in Translating Bluesky's UI (2242s) 50 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mi7pxl6xkz22", // Bluenotes: Community Notes for ATProto (1886s) 51 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mi7pjfdkhv2b", // Waiting for the Future to Load (2561s) 52 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mi7ok5zmuk2k", // How to have more non-english speaking users (1722s) 53 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mi7ofq7ob72a", // One Year of Graze - lessons learned funding, building, and growing in the atmosphere (1178s) 54 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mi7o5amqqx2d", // Bringing Self Sovereign Identities to the Masses via ATproto (1959s) 55 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mi7mb4jbag23", // tangled: The Lewis end (2298s) 56 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mi7ldfbjwe26", // How and Why News Organizations Should Build on the ATProtocol (3011s) 57 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mi7lapdbjc2t", // Roomy and community organizing for system change (3513s) 58 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mi7kaogqjs22", // npmx - a fast, modern browser for the npm registry (2133s) 59 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mi7jorroaa2h", // Day 2 Opening Remarks! (1650s) 60 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mi5wqocga62h", // Closing remarks, I guess, if i have to. (856s) 61 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mi5uqr2spg2l", // Hypercerts on ATProto: Collective Funding, Evaluation, and Ownership as Social Data (1863s) 62 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mi5unzkbat27", // Journalism must create its own algorithms (2245s) 63 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mi5unhqisv22", // This Title Left Intentionally Blank (2153s) 64 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mi5stzyxji2e", // How Streamplace Works: VODs (2020s) 65 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mi5spj6izy2a", // The Phoenix Architecture (2060s) 66 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mi5sn7zmfy23", // A Free Press needs Free Protocols (2146s) 67 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mi5s5mqmgj2r", // Pollen: Prototyping a toolkit for journalists and researchers to restore source transparency in an AI-saturated feed (727s) 68 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mi5s4foj7h2a", // Oaklog: Building a community calendar in the Oakland Bay Area (556s) 69 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mi5s2x6tkd2d", // Burning down data walls in the US Fire Service and Beyond (676s) 70 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mi5rnhjugb2h", // E2EE DMs for Solidarity Social (544s) 71 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mi5rm4y7ts2b", // The Future of Open Source is Social (474s) 72 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mi5rl4r4a725", // Bridging Social Graphs: How Sky Follower Bridge helps people move to Bluesky (580s) 73 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mi5r2rp7a62e", // How (de)centralized is Bluesky, really? (607s) 74 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mi5qzkwfe42z", // Who, Where, Why, What about W Social (586s) 75 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mi5qywid6z25", // What 350,000 users taught me about growing on Open Social (640s) 76 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mi5q57diht27", // Semble: Rediscovering the Magic of Trails (906s) 77 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mi5q4ey4232y", // Stop Hallucinating the Protocol: Grounding your AI Agents with the Official ATproto Docs (1001s) 78 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mi5q3oibtu2i", // Why Gander Social? (1004s) 79 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mi5nh7yjb326", // THE AtmosYear 2026 (2771s) 80 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mi5lexqbqf2z", // Building Public-Interest Infrastructure on ATProto (1617s) 81 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mi5ldvd46r2i", // From protocol to product: How Expo powers the next wave of AT Proto applications (2216s) 82 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mi5lb763vn2j", // Account logic in ATProto using Trusted Execution Environments (2014s) 83 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mi5k3brfax2b", // Rethinking the Client: Why User Choice is the Key to Growth for ATProto (1271s) 84 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mi5jrjmk6y2n", // Open social tech and geopolitical risk (1716s) 85 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mi5jmsg6kn2m", // Consent Before Cryptography (1794s) 86 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mi5itmi65s2z", // Feeds Are The New Websites (816s) 87 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mi5hza73vs2z", // Sattestations (870s) 88 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mi5hy457fu2r", // Building Cirrus: a single-user, serverless PDS (2236s) 89 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mi5hx4v6cr26", // Advocating for Digital Sovereignty: European Experiences and Global Lessons (1945s) 90 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mi5c65iee42h", // Understanding the Landscape of Custom Feeds on Bluesky (1854s) 91 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mi5bya72ub2d", // A discussion with news creators (2029s) 92 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mi5bcpyqg32a", // Beyond Bluesky: Community infrastructure (1587s) 93 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mi5ag3scgk2k", // Building Future of Artificial Intelligence on AT Protocol (1851s) 94 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mi5aarspma27", // Creators First: Video & Media as the Foundation of a Thriving Creator Economy on ATProto (1858s) 95 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mi5a2y3tej2z", // This isn't over until we all listen to kpop (1319s) 96 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mi56pnvulh2o", // Did Lexicon just accidentally solve the enterprise data problem? (1830s) 97 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mi56n6j2g22d", // Who owns the group chat? Building collaborative spaces on ATProto (1522s) 98 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mi56m3hnrq2z", // The Economics of Sovereign Media: A Roadmap for AT Protocol (1762s) 99 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mi56l4hpil2x", // ho owns the group chat? Building collaborative spaces on ATProto (56s) 100 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mi54oonum62b", // Groundings with my Siblings: Lessons Learned Building for Community (2019s) 101 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mi54nec66s2w", // Feature / Product / Business: A Framework for Sustainable ATProto Projects (2200s) 102 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mi54lyc5ts25", // The Aggregation Era burned journalism institutions to the ground. The federated era is emerging from those embers (2145s) 103 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mi4zoce3a22j", // ATmosphereConf 2026 - Room 2301 (2771s) 104 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mi4ziviq2d25", // ATmosphereConf 2026 - Performance Theater (2708s) 105 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mi4y35l2f425", // ATmosphereConf 2026!!! (4768s) 106 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mi3e7ly25h2b", // https://atmosphereconf.org/#schedule-conf1 (544s) 107 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mi3cjemc6a27", // Everything Everywhere All at Once - an impromtu session - panproto.dev (1804s) 108 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mi3bf7s6zn27", // Everything Everywhere All at Once - an impromtu session (1193s) 109 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mi3ar75zqs23", // Everything Everywhere All at Once - Blaine (670s) 110 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mi37ha3edb23", // How (de)centralized is Bluesky, really? - (1395s) 111 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mi36lcxgce2b", // Narrative strands & memetic lineages in community social data using Community Archive - (921s) 112 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mi35eplsua23", // Studying social media through the Atmosphere - (1273s) 113 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mi34ps3oym2i", // Crowdsourced Research Synthesis on ATProto: Envisioning an Inclusive Future - Jay Patel - @infotainment.bsky.social (673s) 114 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mi33ycoo5d2a", // Future of Science Social Media (784s) 115 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mi2wu5u5rs2i", // The Astrosky Ecosystem: An independent online home for astronomy (5508s) 116 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mi2u6pl6ah2z", // Skysquare is context as a service - Travis Simpson - @skysquare.app (96s) 117 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mi2tfsbq4p25", // Making wisdom together - seams.so - @hyl.st (834s) 118 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mi2tdpailb2m", // Making wisdom together - seams - @hyl.st (51s) 119 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mi2son7re62m", // Building collective intelligence to reduce division at ViewSift @viewsift.com (691s) 120 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mi2ryxrnin2a", // Reproducible, citation-aware automated paper reviews @seanjungblluth.bsky.social (727s) 121 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mi2rtfj5ec2m", // Can decentralists cooperate? Rethinking commons and collective action in the age of platforms and AI (137s) 122 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mi2jdevvu626", // Keynote: Towards Modular Open Science with @row1.ca and @matsulab.com (9111s) 123 - "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mi2ikg6gij26" // ATScience at ATmosphereConf 2026! (814s) 2 + "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3miah6keewv2n", 3 + "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mi7sb5disa2y", 4 + "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mi7jx4xi2g25", 5 + "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mi7jnnnh7i2h", 6 + "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mi7isob4ae2a", 7 + "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mi5dvnqcf72u", 8 + "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mi5dv7xthz26", 9 + "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mi5csvtgdg22", 10 + "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mi2ubr4zq72d", 11 + "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3miafywhnca2r", 12 + "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3miafuv53nh2z", 13 + "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mi5xky7ogz23", 14 + "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mi5wqwpqx72z", 15 + "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mi5wj4mc6t2e", 16 + "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mi5n54d6r42u", 17 + "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mi5mvmovsn2i", 18 + "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mi56l4hpil2x", 19 + "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mi2tdpailb2m", 20 + "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mi2rtfj5ec2m", 21 + "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mi2u6pl6ah2z", 22 + "at://did:plc:rbvrr34edl5ddpuwcubjiost/place.stream.video/3mi3e7ly25h2b" 124 23 ]
+7 -8
public/index.html
··· 485 485 486 486 try { 487 487 const text = await (await fetch('/denied-vods.json')).text(); 488 - const denied = JSON.parse(text.replace(/\/\/.*$/gm, '')); 488 + const denied = JSON.parse(text); 489 489 const denySet = new Set(denied); 490 490 const before = all.length; 491 491 all = all.filter(r => !denySet.has(r.uri)); ··· 704 704 const blob = new Blob([audioInit, audioData], { type: 'video/mp4' }); 705 705 audioEl.src = URL.createObjectURL(blob); 706 706 707 - await new Promise((resolve, reject) => { 708 - const done = () => { audioEl.removeEventListener('canplay', done); audioEl.removeEventListener('error', fail); resolve(); }; 709 - const fail = () => { audioEl.removeEventListener('canplay', done); audioEl.removeEventListener('error', fail); reject(audioEl.error); }; 710 - audioEl.addEventListener('canplay', done, { once: true }); 711 - audioEl.addEventListener('error', fail, { once: true }); 712 - setTimeout(resolve, 3000); 707 + // Wait for the browser to be ready enough to seek 708 + await new Promise(r => { 709 + if (audioEl.readyState >= 1) { r(); return; } 710 + audioEl.addEventListener('loadedmetadata', r, { once: true }); 711 + audioEl.addEventListener('canplay', r, { once: true }); 712 + setTimeout(r, 1000); 713 713 }); 714 714 if (stale()) return; 715 715 716 - // Seek audio to match video position, wait for seek, then play 717 716 audioEl.currentTime = video.currentTime; 718 717 console.log('[TV] Audio seeking to', video.currentTime.toFixed(1) + 's'); 719 718