Skip to content

Repository files navigation

ACCESSGATE

A local, explainable conformance pre-check engine for film accessibility: click a failing audio-description gap, and watsonx drafts a fix, the DCMP validator re-checks it, Granite Guardian screens it, and the row flips green live on an interactive timeline.

CI Live demo License: MIT Python 3.11 IBM AI Builders Challenge July 2026 390 tests

Built for the IBM AI Builders Challenge July 2026, Reimagine Creative Industries with AI track.

"Only 16 of 90 Sundance 2026 films were watchable if you are blind. We fix the rest before they ship."

The locked claim: conformance pre-check: automatable checks plus human-judgment flags. This is not a certifier.


Judge Quick Access

Fastest path to check each thing that matters. No account, no keys.

To verify... Go here
Try it, zero setup Live web app, click LOAD DEMO (no upload, no keys)
Claims are wired, not aspirational IBM Stack, then grep any row in the shipped code
Honesty, live /judges transparency endpoint
It reproduces on your machine Build and Run: git clone, pytest (390 passing), python -m src.engine
Results measured, not asserted Evaluation

Live Demo

Surface URL
Demo video (2:56) https://youtu.be/8PHTCRGrWxM
Web app https://accessgate-web.vercel.app
Mobile app (Android) Native Expo/React Native client, mobile/ — same engine, same backend. Build per mobile/README.md
Mobile app (iOS) TestFlight (public link, install on any iPhone; source in mobile/)
REST API https://accessgate-api.onrender.com
Health check https://accessgate-api.onrender.com/health
Pre-computed demo report https://accessgate-api.onrender.com/demo
GitHub https://github.com/StephenSook/accessgate

Two surfaces, one live engine. The web app and a native mobile app (Expo/React Native, mobile/) are both real clients of the same backend: load the demo report and Granite executive summary, review the flagged rules with their standard citations, and run the gated generative fix on a silent gap. Mobile also checks a caption file picked on-device. See mobile/README.md to run it.

Open the web app and click LOAD DEMO to see the full conformance timeline, rule results table, NER score, and gap markers, no file upload needed. The demo runs on a Night of the Living Dead segment (United States public domain) whose caption and audio-description sidecars carry realistic conformance defects. Uploading your own caption file on the live site runs the same 23-rule engine on the hosted backend.

QR code to the AccessGate Android app source
Android app
scan or mobile/ source
QR code to join the AccessGate iOS TestFlight
iOS TestFlight
scan or join link

To run the full live engine with Ollama models locally, see Build and Run.


The Problem

At Sundance 2026, only 16 of 90 feature films offered audio description, down from 26 in 2024. Festivals, distributors, and streaming platforms reject non-compliant caption and audio-description files using automated QC pipelines. Manual QC costs $9-$14/min for audio description. No open-source tool checks both caption and audio-description conformance against WCAG 2.2, FCC 47 CFR 79.1(j)(2), DCMP, and Netflix standards simultaneously. ADA Title II compliance deadlines arrive April 2027 and April 2028.

A real audio-description user on what bad AD feels like (recruited via the ACB Audio Description Project community; name withheld for privacy, consent on file):

"Really bad audio description gives me too much info, and sometimes too little info."

That balance, never too sparse, never overcrowded, sized to the gap, is exactly the DCMP Description Key rule AccessGate scores. The same user also flagged audio description mixed too quietly under the soundtrack, a final-mix issue AccessGate does not check: it scores the audio-description sidecar's structure, timing, and gap-fit, not the delivered mix loudness. That boundary is stated on the /judges page.


What It Does

Two accessibility surfaces, two audiences. Captions are what make a film usable for Deaf and hard-of-hearing viewers; audio description is what makes it usable for blind and low-vision viewers. AccessGate checks both, against the same coded standards.

AccessGate ingests a film plus its caption (.srt/.vtt) and audio-description (.vtt) sidecar files, scores them against 23 coded rules across four standards families, and returns a per-rule pass/fail report where every flag cites the exact standard text it came from, retrieved at runtime rather than mapped rule-to-string. The corpus it retrieves over is the six Docling-parsed standard pages (210 of 222 chunks) plus committed short-form clause text for the same six standards (12 chunks), so a citation can quote either the source page or the crisp clause wording, whichever the query actually matches. The retrieval is Granite-backed on both paths, so the corpus is never re-embedded at request time (the query itself is embedded per lookup). The repo ships one prebuilt vector set per encoder, so nothing re-embeds on startup: a local install loads vectors built with Granite Embedding r2 through sentence-transformers, and the hosted deploy loads vectors built with watsonx-hosted Granite (ibm/granite-embedding-278m-multilingual). Both are committed, both cover the same 222 chunks, and /judges reports citation_provenance.serving so you can see which set actually answered. Building a hosted-encoder index is a deliberate offline step behind ACCESSGATE_ALLOW_HOSTED_REINDEX=1; a metered encoder is never allowed to re-embed the corpus at request time, because doing that on every cold start is what exhausted a month of quota in a day on 2026-07-27. A deterministic character n-gram encoder remains underneath both, so citations still resolve with every hosted API deleted.

Every flag is verifiable, not guessed. Run it on a real broadcast-defective caption file and each finding traces to the exact FCC, WCAG, DCMP, or Netflix text a human reviewer can open and check, not a black-box score. The same report speaks to two audiences: the rule-by-rule citations for compliance engineers, and a plain-English watsonx executive summary for producers and other non-technical stakeholders.

Click a failing audio-description gap on the conformance timeline and the gated fix loop runs: a vision model drafts a description sized to fit the silent window, the DCMP structure validator re-checks it, Granite Guardian screens it for content safety, and the row flips green live. On the hosted demo the drafter is watsonx-hosted Llama 3.2 Vision; run it locally and the drafter is Granite Vision 3.2. The screen is Granite Guardian either way.

Each of the 23 rules is a contract, not a guess, and the output is a file you can use. A deterministic evaluator either holds or it names the exact clause it broke, so a finding is a guarantee a human can verify, never an LLM's opinion. And AccessGate exports into the tools that actually fix the file: the flagged cues write to editor-native formats (a findings CSV and navigable WebVTT markers, src/exporters/editor.py, example artifacts in data/demo/editor_exports/) alongside the SARIF 2.1.0 and OSCAL POA&M compliance documents. A captioner opens the result in their own workflow instead of reading a report. (src/exporters/editor.py also carries a gated-AD-drafts WebVTT writer, export_ad_descriptions_vtt, which emits only fixes that passed the full gate. It is unit-tested but no shipped surface calls it yet, because accepted drafts are not retained server-side, so it is a library function rather than a product output.)

And the review of that report is itself auditable and drivable in plain English. Beyond the one-shot report, AccessGate opens an event-sourced review session: a QC lead accepts, dismisses (with a reason), flags, or annotates each finding and accepts or rejects the gated fixes, as reversible typed operations against the findings. Every operation carries a server-computed inverse, so undo is deterministic, and the whole session replays from its append-only log, a tamper-evident audit trail of who decided what and why. The session takes plain English (dismiss every reading-speed flag after two minutes as acceptable for this title): watsonx-hosted Granite compiles the instruction into a structured intent that is then re-grounded against the report's real findings through the same deterministic selector, so it can never act on a rule id or timecode the engine did not produce (a deterministic keyword compiler runs when no key is present). See src/review_session.py and the /review/* endpoints.

Delete every hosted AI API. The engine still runs and still produces a report. That property, plus a deep and genuinely load-bearing IBM stack built through IBM Bob, is the differentiator.

To our knowledge, AccessGate is the first tool that is all of these at once: open, explainable, covering both captions and audio description, citing the exact standard clause behind every flag, and drafting a gated generative fix. Commercial timed-text QC tools exist, but none are open, cover both surfaces, cite the standard text, and fix the gap. The novelty is the intersection, not any single feature.


AccessGate in One Loop

A film's caption file has a 45-character line, a 0.8-second cue, a 660-wpm burst, and 150 speech regions with no caption coverage. Its audio-description file has a line with more words than its gap can carry at 150 wpm, three lines that overlap detected speech, and three the parser reads as sentence fragments. The NER caption score lands at 78.92%, below 98%, but ASR carries measured racial disparity (Koenecke et al., PNAS 2020: WER 0.35 for Black speakers vs 0.19 for white), so the band is flagged for human review, never auto-failed. Every flag cites the exact standard section that governs it. Click the failing AD gap at 39.1s. The vision drafter writes a present-tense, active-voice, third-person description that fits the 5.9-second window (watsonx-hosted Llama 3.2 Vision on the deploy, Granite Vision 3.2 locally). The DCMP validator passes it. Granite Guardian clears it. The row flips green.


Architecture

flowchart TB
    subgraph Input
        F["Film / Video"]
        CAP["Captions (.srt/.vtt)"]
        AD["Audio Description (.vtt)"]
    end

    subgraph TIMING["Timing Engine (self-built, API-deletion-proof)"]
        direction LR
        FW["faster-whisper\nword_timestamps=True"]
        VAD["Silero VAD\nspeech regions"]
        GAP["Gap Engine\ncomplement above 2.5s"]
        FW --> GAP
        VAD --> GAP
    end

    subgraph SCORE["Scoring Engine (self-built, API-deletion-proof)"]
        direction LR
        GS["Granite Speech 3.3-2b\nreference transcript"]
        NER["NER Scorer\n(N-E-R)/N + confidence band"]
        CLS["Error-Type Classifier\nmacro-F1 0.952\n(offline CLI, not in the live path)"]
        GS --> NER
    end

    subgraph RULES["23-Rule Evaluator Engine (self-built, API-deletion-proof)"]
        direction LR
        FCC["FCC 47 CFR 79.1"]
        WCAG["WCAG 2.2\nSC 1.2.2 / 1.2.5"]
        DCMP["DCMP Caption\n+ Description Keys"]
        NFLX["Netflix TTSG"]
        RAG["Granite Embedding r2\nRAG citations from standards"]
    end

    subgraph EXPORT
        SARIF["SARIF 2.1.0\n(timecodes in property bags)"]
        OSCAL["OSCAL POA&M v1.1.2"]
    end

    subgraph GENFIX["Gated Generative Fix (on gap click)"]
        direction LR
        GV["Granite Vision 3.2\ndraft AD description (local)"]
        WXV["watsonx-hosted Llama 3.2 Vision\ndraft AD description (hosted demo)"]
        DCMPV["DCMP Structure\nValidator (self-built)"]
        GG["Granite Guardian\ncontent safety screen\n(3:2b local / 3-8b watsonx)"]
        WX["watsonx.ai Lite\nhosted side-by-side"]
        GV --> DCMPV --> GG
        WXV --> DCMPV
        GV -.-> WX
    end

    subgraph UI["React + IBM Carbon SPA"]
        TL["Interactive Conformance\nTimeline"]
        TBL["Rule Results Table\n(expandable citations)"]
        PANEL["Gated Fix Panel\n(Stage 1-2-3-4)"]
        AXE["axe-core A11Y badge\n(app audits itself)"]
    end

    F --> TIMING
    CAP --> TIMING
    F --> SCORE
    TIMING --> RULES
    SCORE --> RULES
    AD --> RULES
    RULES --> EXPORT
    RULES --> UI
    UI -->|gap click| GENFIX
    GENFIX --> UI
Loading

IBM Stack (what is actually wired)

AccessGate runs on five IBM Granite model families (Vision, Guardian, Speech, Embedding, and Granite 3 8B via watsonx.ai), plus watsonx-hosted vision and Docling, every one wired in the shipped code, not a badge. Every row below states exactly how, because honest labeling is the point: a judge can grep any claim, and where the hosted free-tier deploy runs a different path than a local install, the row says so. See the live /judges endpoint for the same breakdown.

IBM Tool Role Wiring
IBM Bob Primary development tool: authored the conformance engine, the test suite, and the frontend; parallel subagents; custom mode; conformance Skill; Plan specs; two /review audits (SARIF + OSCAL); self-referential MCP loop. Deployment and later Granite Speech wiring / UI refinements were finished with other tooling after Bob credits ran out. Primary development tool
Granite Speech 3.3-2b High-accuracy reference transcript feeding the NER scorer Wired, local transformers (src/granite_speech.py, opt-in ACCESSGATE_GRANITE_SPEECH=1; faster-whisper is the default reference because Granite Speech is ~20x realtime on CPU)
Granite Vision 3.2 2b Drafts the AD fix on a failing gap Wired, local Ollama (src/generative_fix.py)
Granite Guardian 3 2b Screens generated AD for content safety before the row flips green, local path Wired, local Ollama (src/generative_fix.py)
Granite Guardian 3 8b The same safety gate on the hosted demo, where there is no Ollama. This is the screen a judge actually triggers from the live site Wired, hosted (src/watsonx_guardian.py, ibm/granite-guardian-3-8b)
Granite Embedding r2 Embeds the standards corpus so citations are retrieved at runtime, never hardcoded, on a local install Wired, sentence-transformers (src/rag.py)
Granite Embedding (watsonx.ai) Embeds the standards corpus for the hosted deploy's citation retrieval. Built offline and committed, so the deploy loads Granite vectors with zero embedding calls at request time Wired, hosted (src/watsonx_embedding.py, ibm/granite-embedding-278m-multilingual); index built behind ACCESSGATE_ALLOW_HOSTED_REINDEX=1
watsonx.ai (granite-3-8b-instruct) Hosted AD-line generation and a plain-English report summary (src/report_summary.py), side by side with the local Granite path Wired, hosted (src/watsonx_showcase.py)
watsonx-hosted vision (Llama 3.2 11B) Drafts the gap fix live on the hosted demo where there is no Ollama (/demo-fix); Granite Vision is the local model Wired, src/watsonx_vision.py
Docling Parses the WCAG, FCC, DCMP and Netflix source pages into the markdown corpus the RAG cites. Those 6 parsed pages are 210 of the index's 222 chunks; the other 12 are committed short-form clause text for the same standards Wired, scripts/parse_standards.pystandards/parsed/ (6 docs)
AI FactSheet model card Governance doc for the trained classifier: training data, evaluation, and ASR-disparity bias handling data/training/model_card.md

Four Self-Built Load-Bearing Artifacts

Each passes the API-deletion test: remove every hosted AI API and each still runs.

  1. Conformance rule engine: NER scorer ((N-E-R)/N, Romero-Fresco/Ofcom broadcast model), 98% threshold, confidence bands, never auto-fails on ASR alone per Koenecke et al. PNAS 2020
  2. Dialogue-gap detection and timing engine: two-tier speech detection (Silero VAD attempted first, then a pure-stdlib RMS energy detector), gap complement above 2.5s minimum, merged across sub-300ms blips. With the dependency set this repo ships, Silero declines to load and the RMS detector is what produces the demo's 197 speech regions and 3 gaps, which is exactly why this artifact survives the API-deletion test: the working path needs only wave, struct, and math
  3. Audio-description structure validator: DCMP rules: word-count-fits-gap, no-overlap-with-dialogue, present-tense, active-voice, third-person, objectivity flags
  4. Caption error-type classifier: supervised logistic regression on a synthetic weak-labeled set, distinguishes recognition errors (ASR mishears) from edition errors (paraphrase/omission); macro-F1: 0.952. This one is a standalone offline module, run with python -m src.classifier --synthetic: no code path in the live /check reaches it, and the conformance verdict never depends on it. Saying so because the alternative is the defect that graded a rival D- this cycle, a real deterministic engine that nothing imported behind a README implying it was what ran.

Evaluation (measured, not asserted)

Verify the central claim yourself, in one command, with no setup:

git clone https://github.com/StephenSook/accessgate && cd accessgate
pip install pytest          # the only dependency: the test runner itself
python3 -m pytest tests/test_citations_are_never_fabricated.py -q

No project dependencies, no virtualenv, no network, no API key. That test imports only json, re and pathlib from the standard library, and reads the Docling-parsed standards corpus committed at standards/index/chunks.json (222 chunks, 105 KB). It asserts every clause this engine cites is a verbatim substring of that corpus, so a citation cannot be composed, paraphrased, or model-authored. It runs in well under a second, and it runs in CI on every push.

That is the claim worth checking hardest, because it is the one most often asserted and least often enforced: two rivals this cycle render synthesized prose in a citation slot, one beneath a "CONFIRMED AUDIT" badge.

Which of these gates has been proven to fail when broken, rather than merely observed passing, is recorded in docs/PROVEN_GATES.md: a log of mutations actually applied to a working tree, the assertion that caught each one, and an explicit statement of what it does not claim.

Metric Value Source
Classifier macro-F1 0.952 synthetic held-out set, 3-class, n=140, reproduce with python -m src.classifier --synthetic
Rule engine: violations detected 6 / 10 on the files; 10 / 10 on the unit fixtures data/demo/notld_broken.srt + notld_broken_ad.vtt degradation recipe
Rule engine on real machine captions 94 real defects / 8 rules faster-whisper on the real NOTLD audio, no injected defects (data/demo/notld_real_autocaption.srt)
SARIF schema valid pass python scripts/validate_sarif.py in CI (against the vendored SARIF 2.1.0 schema; sarif-multitool is unusable on ubuntu-24.04 runners)
axe-core A11Y score 100% App audits its own UI on every load
Tests passing 390 pytest on a fresh clone; CI gates Python 3.11 (the code also compiles on 3.12, which CI does not gate)
NER caption accuracy, demo file ~78% Reproduces to within about a point, see the note below

Why the NER figure is quoted approximately. The NER score is measured against a reference transcript produced by ASR, and ASR is not bit-deterministic across runs and model builds. The committed demo report (data/demo/demo_report.json, what the hosted /demo serves) records 78.92%; a fresh clone re-running the engine on the same audio measured 78.9%. Everything deterministic about that run is identical between the two: the same 31 rule results with the same pass, fail, and flag statuses, the same 3 dialogue-free gaps, the same 197 speech regions. Only the ASR-derived accuracy figure moves, which is exactly why this project never auto-fails a caption on ASR evidence alone.

Verified on real, naturally-defective captions, not just an injected demo. The 10/10 row is a designed showcase (a hand-authored degradation recipe). To prove the engine on real data, we transcribed the public-domain Night of the Living Dead audio with faster-whisper and ran the 23 rules on that raw machine-caption output. With zero injected defects, AccessGate flagged 94 real violations across 8 rules: 40 over-long lines (DCMP-CAP-01, NFLX-LEN-01), 8 reading-speed breaches (DCMP-CAP-03, NFLX-CPS-01), and 7 sub-minimum-duration cues (DCMP-CAP-04, NFLX-DUR-01). Machine captions are the single most common real-world accessibility defect, and the run is reproducible: python scripts/transcribe_real_captions.py.


How IBM Bob Was Used

IBM Bob was the primary development tool. It authored the conformance engine (~4,900 lines across src/, including the 23 rule evaluators, the NER scorer, the VAD gap engine, and the SARIF/OSCAL exporters), the test suite, and the React frontend (~2,400 lines). Bob's own line-level attribution records for this repository are committed at bob_sessions/bob-attribution-recovered.json.

The test count is split honestly, because Bob did not write all of it. The build trace below shows the suite standing at 172 tests when Bob's credits ran out on 2026-07-13. It stands at 390 today; the difference was added afterwards with other tooling, alongside deployment, the Granite Speech wiring, and the UI and honesty refinements. So the claim is Bob as primary, not exclusive, and the 390 badge is a repository metric rather than a Bob attribution.

The most distinctive setup is a self-referential one: AccessGate's own MCP server (exposing check_conformance, detect_gaps, and score_captions) is registered to Bob in .bob/mcp.json with all three tools pre-authorised, so the tool that built the engine can call the engine. The config and the server are both in this repo; the Bob-side session transcripts are not, so treat this as a wired capability rather than a logged event.

The build itself is in the git history, which is the part you can check without taking our word for anything. The engine core landed in eight commits on 2026-07-13 between 19:53 and 20:40 ET, with the test count carried in each subject line:

Time (ET) Commit Tests
19:53 data models, rule registry loader 6
19:57 caption parser (SRT+VTT) 9
19:58 VAD gap engine + NER scorer 22
20:09 all 23 rule evaluators 108
20:23 caption error-type classifier (macro-F1 0.952) 108
20:34 RAG layer, main engine, SARIF/OSCAL exporters 154
20:40 generative fix loop, MCP server, FastAPI 172

Reproduce it with git log --reverse --format='%ad %s' --date=format:'%H:%M'. Bob credits ran out later that same day, which is why the commits after it shift to deployment, Granite Speech wiring, and honesty refinements done with other tooling.

Evidence Location
Custom mode (accessibility-compliance-engineer) .bob/custom_modes.yaml
Conformance rule-authoring skill .bob/skills/conformance/SKILL.md
/review audit 1 (SARIF, tool.driver.name is IBM Bob) security/review-audit-1.sarif
/review audit 2 (OSCAL POA&M) security/review-audit-2.oscal.json
Self-referential MCP config .bob/mcp.json
Bob admin subscription screenshot bob_sessions/bob-subscription-usage.png
Engine build trace git log, 2026-07-13 19:53 to 20:40 ET

Build and Run

# 1. Clone and install
git clone https://github.com/StephenSook/accessgate.git
cd accessgate
pip install -r requirements.txt

# 2. Pull Ollama models (requires Ollama running locally)
ollama pull granite3.2-vision:2b   # drafts the gated AD fix locally
ollama pull granite3-guardian:2b   # screens that draft locally

# 3. Copy env template
cp .env.example .env  # fill in WATSONX_API_KEY + WATSONX_PROJECT if you have them

# 4. Run the conformance engine (CLI): <film/audio> <caption> [audio-description]
# Writes JSON + SARIF + OSCAL to outputs/. Exits non-zero when conformance fails.
# The 3 dialogue-free gaps come from VAD on the audio track.
python -m src.engine data/demo/notld_segment_16k.wav data/demo/notld_broken.srt data/demo/notld_broken_ad.vtt

# 5. Run tests
pytest

# 6. Start the API server
uvicorn src.app:app --reload --port 8000

# 7. Start the frontend (separate terminal)
cd frontend && npm install && npm run dev
# Open http://localhost:5173

# 8. Lint SARIF export (validates against the vendored SARIF 2.1.0 schema)
python scripts/validate_sarif.py security/review-audit-1.sarif

Repository Structure

accessgate/
├── src/
│   ├── engine.py              # Main CLI entry point
│   ├── models.py              # Pydantic data models
│   ├── registry.py            # Rule registry loader
│   ├── caption_parser.py      # SRT/VTT parser
│   ├── gap_engine.py          # Silero VAD gap detector
│   ├── ner_scorer.py          # NER-style caption scorer
│   ├── classifier.py          # Error-type classifier (macro-F1 0.952)
│   ├── rag.py                 # Granite Embedding RAG layer
│   ├── generative_fix.py      # Granite Vision -> DCMP -> Guardian fix loop
│   ├── app.py                 # FastAPI REST server + /demo endpoint
│   ├── live_monitor.py        # Sliding-window live caption monitor
│   ├── watsonx_showcase.py    # watsonx.ai Lite hosted showcase call
│   ├── evaluators/            # fcc.py, wcag.py, dcmp_caption.py, dcmp_desc.py, netflix.py
│   ├── exporters/             # sarif.py (2.1.0), oscal.py (POA&M v1.1.2)
│   └── mcp_server/            # FastMCP server (self-referential IBM Bob loop)
├── rules/rules_registry.yaml  # 23 rules across FCC / WCAG / DCMP / Netflix
├── standards/                 # Authoritative standards corpus + Granite Embedding index
├── data/
│   ├── demo/                  # notld_broken.srt, notld_broken_ad.vtt, demo_report.json
│   └── training/
│       ├── model_card.md      # IBM AI FactSheet for the classifier
│       └── label_schema.md    # Annotation schema
├── frontend/                  # Vite + React + IBM Carbon SPA
├── mobile/                    # Expo / React Native (iOS + Android) client
├── security/                  # SARIF + OSCAL /review audit outputs
├── bob_sessions/              # IBM Bob usage evidence (admin subscription screenshot)
├── tests/                     # 390 passing tests
├── render.yaml                # Render deployment config (FastAPI backend)
├── AGENTS.md                  # Project policy spine (read every session)
└── .bob/                      # Custom mode, conformance skill, MCP config

Selected Challenge Theme

Reimagine Creative Industries with AI: AccessGate reimagines the post-production accessibility step that determines whether blind, low-vision, Deaf, and hard-of-hearing audiences can experience a film at all. It removes the manual QC bottleneck between a finished film and its full audience.

The same rule-engine-plus-gated-fix architecture generalizes to music rights conformance and dubbing QA.

Who deploys it. A studio, streamer, festival, or post-production house runs AccessGate as the caption-and-audio-description QC gate between a finished film and its release, and the live /judges page doubles as that operator's transparency console: every claim traces to a live endpoint. It is a product a QC team could drop into their pipeline on Monday, not a concept.


Real-World Impact

  • ADA Title II compliance deadlines: April 26, 2027 (population 50,000+) and April 26, 2028 (smaller entities)
  • India MIB mandated audio description and closed captions for theatrical films (O.M. 15.03.2024) and OTT platforms (06.02.2026)
  • Netflix auto-QC rejects non-compliant timed-text files before human review
  • Manual AD QC costs $9-$14/min, AccessGate reduces the pre-check step to seconds
  • The accessibility tool passes its own accessibility audit (axe-core, A11Y 100%)
  • Validated by a real screen-reader user. An audio-description user tested the live app with the JAWS screen reader and reported it "very accessible," with "all labels read correctly" (film, captions, audio description, and the controls). Two of their suggestions, a heading outline and a skip-to-content link, shipped the same day. Consent on file.

Demo Assets

  • Night of the Living Dead (1968): US public domain (published without valid copyright notice). Source: archive.org/details/night-of-the-living-dead_1968
  • Big Buck Bunny: CC BY 3.0. Attribution: (c) copyright 2008, Blender Foundation / www.bigbuckbunny.org

See NOTICE for full third-party attribution.


SkillsBuild

Every team member has completed an IBM SkillsBuild learning activity. The completion certificate is submitted on the BeMyApp project page.


License

MIT. See LICENSE. See NOTICE for third-party media and training-data attribution.

About

Local, explainable film accessibility conformance pre-check engine. IBM AI Builders Challenge July 2026.

Topics

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages