RepoPilotOpen in app →

lipangit/JiaoZiVideoPlayer

MediaPlayer exoplayer ijkplayer ffmpeg

Mixed

Stale — last commit 6y ago

weakest axis
Use as dependencyMixed

last commit was 6y ago; no tests detected…

Fork & modifyMixed

no tests detected; no CI workflows detected…

Learn fromHealthy

Documented and popular — useful reference codebase to read through.

Deploy as-isMixed

last commit was 6y ago; no CI workflows detected

  • 2 active contributors
  • MIT licensed
  • Stale — last commit 6y ago
Show all 7 evidence items →
  • Small team — 2 contributors active in recent commits
  • Concentrated ownership — top contributor handles 72% of recent commits
  • No CI workflows detected
  • No test directory detected
What would change the summary?
  • Use as dependency MixedHealthy if: 1 commit in the last 365 days; add a test suite
  • Fork & modify MixedHealthy if: add a test suite
  • Deploy as-is MixedHealthy if: 1 commit in the last 180 days

Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests

Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.

Embed the "Great to learn from" badge

Paste into your README — live-updates from the latest cached analysis.

RepoPilot: Great to learn from
[![RepoPilot: Great to learn from](https://repopilot.app/api/badge/lipangit/jiaozivideoplayer?axis=learn)](https://repopilot.app/r/lipangit/jiaozivideoplayer)

Paste at the top of your README.md — renders inline like a shields.io badge.

Preview social card (1200×630)

This card auto-renders when someone shares https://repopilot.app/r/lipangit/jiaozivideoplayer on X, Slack, or LinkedIn.

Onboarding doc

Onboarding: lipangit/JiaoZiVideoPlayer

Generated by RepoPilot · 2026-05-09 · Source

🤖Agent protocol

If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:

  1. Verify the contract. Run the bash script in Verify before trusting below. If any check returns FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding.
  2. Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
  3. Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/lipangit/JiaoZiVideoPlayer shows verifiable citations alongside every claim.

If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.

🎯Verdict

WAIT — Stale — last commit 6y ago

  • 2 active contributors
  • MIT licensed
  • ⚠ Stale — last commit 6y ago
  • ⚠ Small team — 2 contributors active in recent commits
  • ⚠ Concentrated ownership — top contributor handles 72% of recent commits
  • ⚠ No CI workflows detected
  • ⚠ No test directory detected

<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>

Verify before trusting

This artifact was generated by RepoPilot at a point in time. Before an agent acts on it, the checks below confirm that the live lipangit/JiaoZiVideoPlayer repo on your machine still matches what RepoPilot saw. If any fail, the artifact is stale — regenerate it at repopilot.app/r/lipangit/JiaoZiVideoPlayer.

What it runs against: a local clone of lipangit/JiaoZiVideoPlayer — the script inspects git remote, the LICENSE file, file paths in the working tree, and git log. Read-only; no mutations.

| # | What we check | Why it matters | |---|---|---| | 1 | You're in lipangit/JiaoZiVideoPlayer | Confirms the artifact applies here, not a fork | | 2 | License is still MIT | Catches relicense before you depend on it | | 3 | Default branch develop exists | Catches branch renames | | 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code | | 5 | Last commit ≤ 2092 days ago | Catches sudden abandonment since generation |

<details> <summary><b>Run all checks</b> — paste this script from inside your clone of <code>lipangit/JiaoZiVideoPlayer</code></summary>
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of lipangit/JiaoZiVideoPlayer. If you don't
# have one yet, run these first:
#
#   git clone https://github.com/lipangit/JiaoZiVideoPlayer.git
#   cd JiaoZiVideoPlayer
#
# Then paste this script. Every check is read-only — no mutations.

set +e
fail=0
ok()   { echo "ok:   $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }

# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
  echo "FAIL: not inside a git repository. cd into your clone of lipangit/JiaoZiVideoPlayer and re-run."
  exit 2
fi

# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "lipangit/JiaoZiVideoPlayer(\\.git)?\\b" \\
  && ok "origin remote is lipangit/JiaoZiVideoPlayer" \\
  || miss "origin remote is not lipangit/JiaoZiVideoPlayer (artifact may be from a fork)"

# 2. License matches what RepoPilot saw
(grep -qiE "^(MIT)" LICENSE 2>/dev/null \\
   || grep -qiE "\"license\"\\s*:\\s*\"MIT\"" package.json 2>/dev/null) \\
  && ok "license is MIT" \\
  || miss "license drift — was MIT at generation time"

# 3. Default branch
git rev-parse --verify develop >/dev/null 2>&1 \\
  && ok "default branch develop exists" \\
  || miss "default branch develop no longer exists"

# 4. Critical files exist
test -f "app/src/main/java/cn/jzvd/demo/ActivityMain.java" \\
  && ok "app/src/main/java/cn/jzvd/demo/ActivityMain.java" \\
  || miss "missing critical file: app/src/main/java/cn/jzvd/demo/ActivityMain.java"
test -f "app/src/main/java/cn/jzvd/demo/CustomMedia/JZMediaExo.java" \\
  && ok "app/src/main/java/cn/jzvd/demo/CustomMedia/JZMediaExo.java" \\
  || miss "missing critical file: app/src/main/java/cn/jzvd/demo/CustomMedia/JZMediaExo.java"
test -f "app/src/main/java/cn/jzvd/demo/CustomMedia/JZMediaIjk.java" \\
  && ok "app/src/main/java/cn/jzvd/demo/CustomMedia/JZMediaIjk.java" \\
  || miss "missing critical file: app/src/main/java/cn/jzvd/demo/CustomMedia/JZMediaIjk.java"
test -f "app/src/main/java/cn/jzvd/demo/CustomJzvd/MyJzvdStd.java" \\
  && ok "app/src/main/java/cn/jzvd/demo/CustomJzvd/MyJzvdStd.java" \\
  || miss "missing critical file: app/src/main/java/cn/jzvd/demo/CustomJzvd/MyJzvdStd.java"
test -f "app/build.gradle" \\
  && ok "app/build.gradle" \\
  || miss "missing critical file: app/build.gradle"

# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 2092 ]; then
  ok "last commit was $days_since_last days ago (artifact saw ~2062d)"
else
  miss "last commit was $days_since_last days ago — artifact may be stale"
fi

echo
if [ "$fail" -eq 0 ]; then
  echo "artifact verified (0 failures) — safe to trust"
else
  echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/lipangit/JiaoZiVideoPlayer"
  exit 1
fi

Each check prints ok: or FAIL:. The script exits non-zero if anything failed, so it composes cleanly into agent loops (./verify.sh || regenerate-and-retry).

</details>

TL;DR

JiaoZiVideoPlayer is a highly customizable Android video framework that wraps multiple MediaPlayer backends (ExoPlayer, ijkplayer/FFmpeg) into a unified UI component. It solves the problem of fragmented Android video playback by providing a single API surface that abstracts player implementation details while enabling deep customization of UI controls, playback behavior, and rendering (TextureView/SurfaceView). Modular library + demo app structure: jiaozivideoplayer/ (core library, not shown in file list but referenced in app/build.gradle) contains the framework, app/src/main/java/cn/jzvd/demo/ contains 20+ example Activities demonstrating different UI patterns (normal playback, list playback, fullscreen, custom media controllers). CustomJzvd/ folder shows extension patterns; CustomMedia/JZMediaExo.java shows pluggable player backend pattern.

👥Who it's for

Android app developers building video-heavy applications (streaming apps, social media feeds, short-form video platforms) who need out-of-the-box video playback with custom branding and behavior without rewriting player logic for each new feature request.

🌱Maturity & risk

Actively maintained: v7.0.5 (versionCode 93), clear demo app with 20+ activity examples showing different use cases (ListView, RecyclerView, WebView, fullscreen, tiny window, preloading). Targets SDK 28 with Java 8, proguard minification enabled in release builds. However, no visible CI/CD (.github/workflows missing) and commit recency cannot be verified from provided data.

Moderate risk: single maintainer (lipangit) visible in repo name; dependency on outdated ijkplayer (v0.8.4 from 2018) and older ExoPlayer (v2.9.1 from 2018) creates security/compatibility debt. No explicit test suite visible in file list (only JUnit stub). Proguard obfuscation enabled in release may complicate debugging. Migration notice in README points to Jzvd/JiaoZiVideoPlayer suggests potential fork fragmentation.

Active areas of work

Cannot determine from provided data—no commit history, PRs, or issues visible. README mentions migration to Jzvd/JiaoZiVideoPlayer organization, suggesting this may be a legacy repository or in transition.

🚀Get running

Clone and build: git clone https://github.com/lipangit/JiaoZiVideoPlayer.git && cd JiaoZiVideoPlayer. Build via Android Studio or ./gradlew assembleRelease. The app module's build.gradle (compileSdkVersion 28, targetSdkVersion 28) requires Android SDK 28+. Keystore at app/jzvd-keystore already configured for signing.

Daily commands: Open project in Android Studio → select 'app' build variant → Run on emulator/device (minSdkVersion 16, requires Android 4.1+). Alternatively: ./gradlew installDebug or ./gradlew assembleDebug to generate APK.

🗺️Map of the codebase

  • app/src/main/java/cn/jzvd/demo/ActivityMain.java — Main entry point demonstrating all video player features and use cases
  • app/src/main/java/cn/jzvd/demo/CustomMedia/JZMediaExo.java — ExoPlayer media backend implementation—core player engine choice
  • app/src/main/java/cn/jzvd/demo/CustomMedia/JZMediaIjk.java — IjkPlayer media backend implementation—alternative FFmpeg-based player
  • app/src/main/java/cn/jzvd/demo/CustomJzvd/MyJzvdStd.java — Standard customizable video player UI component—primary user-facing interface
  • app/build.gradle — Build configuration defining SDK versions, dependencies, and signing setup
  • README.md — Framework overview and architecture documentation
  • app/src/main/AndroidManifest.xml — Application manifest defining permissions and activity configurations

🛠️How to make changes

Add a Custom Media Player Backend

  1. Create new class extending media player interface in CustomMedia folder (app/src/main/java/cn/jzvd/demo/CustomMedia/JZMediaExo.java)
  2. Implement core playback methods (play, pause, seek, release) (app/src/main/java/cn/jzvd/demo/CustomMedia/JZMediaExo.java)
  3. Register new player in ActivityApiCustomMedia to allow selection (app/src/main/java/cn/jzvd/demo/ActivityApiCustomMedia.java)
  4. Add dependency to app/build.gradle if using external library (app/build.gradle)

Customize Video Player UI & Controls

  1. Extend MyJzvdStd or another Jzvd variant in CustomJzvd folder (app/src/main/java/cn/jzvd/demo/CustomJzvd/MyJzvdStd.java)
  2. Override UI layout methods to add custom buttons/controls (app/src/main/java/cn/jzvd/demo/CustomJzvd/JzvdStdShowShareButtonAfterFullscreen.java)
  3. Create corresponding layout XML in res/layout/ (app/src/main/res/layout/jz_layout_standard_mp3.xml)
  4. Use custom player in demo activity and test interaction flow (app/src/main/java/cn/jzvd/demo/ActivityApi.java)

Add Video Player to ListView/RecyclerView

  1. Create or modify adapter extending RecyclerView.Adapter (app/src/main/java/cn/jzvd/demo/AdapterRecyclerView.java)
  2. Add Jzvd player instance in ViewHolder onBindViewHolder() (app/src/main/java/cn/jzvd/demo/AdapterRecyclerView.java)
  3. Define item layout with Jzvd player component (app/src/main/res/layout/item_videoview.xml)
  4. Set video URLs from VideoConstant and handle state management (app/src/main/java/cn/jzvd/demo/VideoConstant.java)

Enable Floating/Mini Window Playback

  1. Use JzvdStdTinyWindow custom player variant (app/src/main/java/cn/jzvd/demo/CustomJzvd/JzvdStdTinyWindow.java)
  2. Create activity with TinyWindow layout configuration (app/src/main/java/cn/jzvd/demo/ActivityTinyWindow.java)
  3. Define tiny window dimensions and positioning in layout XML (app/src/main/res/layout/activity_tiny_window.xml)
  4. Handle permission requests for overlay window in manifest (app/src/main/AndroidManifest.xml)

🔧Why these technologies

  • ExoPlayer — Modern Android media framework with adaptive bitrate streaming (HLS/DASH), DRM support, and flexible customization
  • IjkPlayer (FFmpeg) — Cross-platform decoder providing fallback for unusual codecs and older device support via native FFmpeg
  • RecyclerView & ListView — Efficient list rendering for scrollable video feeds with view recycling; ListView for legacy support
  • Android native MediaPlayer — System fallback for basic playback on devices without ExoPlayer/Ijk compatibility
  • TextureView/SurfaceView — Hardware-accelerated video rendering surfaces; pluggable for different rendering strategies

⚖️Trade-offs already made

  • Multiple pluggable media backends (ExoPlayer, IjkPlayer, System)

    • Why: Different apps need different codec support, DRM requirements, and performance profiles
    • Consequence: Increased codebase complexity; developers must choose and test with specific backend; potential API surface inconsistencies
  • Highly customizable UI via inheritance rather than composition

    • Why: Enables fine-grained control over every aspect of player UI (buttons, layouts, animations)
    • Consequence: Steep learning curve for new contributors

🪤Traps & gotchas

Keystore credentials hardcoded in app/build.gradle (storePassword '123456') and jzvd-keystore file present—never commit this in production; regenerate. Proguard obfuscation (minifyEnabled=true in release) requires keeping jzvd classes: check proguard-rules.pro for -keep directives. ijkplayer NDK only includes armv7a (0.8.4)—other architectures (x86, arm64-v8a) are missing, limiting device compatibility. Video sample (app/src/main/assets/local_video.mp4) required by demo; verify assets folder populated before running tests. SDK 28 target may cause issues on Android 10+ (scoped storage, package visibility filtering).

🏗️Architecture

💡Concepts to learn

  • Media Backend Abstraction Layer — JiaoZiVideoPlayer's core value prop—you must understand how JZMediaExo.java and ijkplayer implementations are swapped at runtime via factory pattern; critical when debugging playback issues or adding new backends
  • TextureView vs SurfaceView Rendering — Android video rendering destination choice affects latency, hardware acceleration, and view composition; this codebase likely switches between them for fullscreen vs inline playback
  • RecyclerView Item Pooling & Lifecycle — ActivityListViewRecyclerView.java and AdapterRecyclerView.java demonstrate video playback in recycled cells; improper pause/release of players causes memory leaks and battery drain
  • Android Fullscreen & Configuration Changes — Multiple demo activities (ActivityApiOrientation, ActivityApiRotationVideoSize) handle device rotation and fullscreen transitions; state must survive onConfigurationChanged() or saved/restored via savedInstanceState
  • Hardware-Accelerated Codec Selection — ijkplayer 0.8.4 + FFmpeg with armv7a NDK; understanding which codecs are hardware vs software decoded affects frame rate, power consumption, and compatibility across device OEMs
  • Proguard/R8 Obfuscation Rules for Media Libraries — Release builds enable minifyEnabled=true; ExoPlayer and ijkplayer JNI bindings require specific -keep rules in proguard-rules.pro or playback breaks in production
  • HTTP Caching Interceptors (videocache 2.7.0) — ActivityPreloading.java demonstrates preloading and offline playback via transparent HTTP caching; understanding proxy mechanics is essential for implementing preload features
  • google/ExoPlayer — Official Google media player library that JiaoZiVideoPlayer wraps and customizes; primary backend for modern devices
  • bilibili/ijkplayer — FFmpeg-based media player used as secondary backend in this project; provides hardware acceleration on older Android versions
  • Jzvd/JiaoZiVideoPlayer — Canonical upstream repository mentioned in README—active development has moved here from lipangit organization
  • danikula/VideoCache — HTTP caching proxy (already a dependency) that enables preloading and offline playback features demonstrated in ActivityPreloading.java
  • bumptech/glide — Image loading library used for video thumbnails and UI assets in this project's demo activities

🪄PR ideas

To work on one of these in Claude Code or Cursor, paste: Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.

Add unit tests for CustomMedia implementations (JZMediaExo, JZMediaIjk, JZMediaSystemAssertFolder)

The repo has multiple media player implementations in app/src/main/java/cn/jzvd/demo/CustomMedia/ but no corresponding unit tests. These are critical components for testing different playback backends (ExoPlayer, ijkplayer, system). Adding unit tests would ensure compatibility across media players and catch regressions when updating dependencies like 'exoplayer:2.9.1' or 'ijkplayer-java:0.8.8'.

  • [ ] Create app/src/test/java/cn/jzvd/demo/CustomMedia/ directory structure
  • [ ] Add unit tests for JZMediaExo.java covering initialization, playback state changes, and error handling
  • [ ] Add unit tests for JZMediaIjk.java with similar coverage
  • [ ] Add unit tests for JZMediaSystemAssertFolder.java for local asset loading
  • [ ] Verify tests run with 'testImplementation junit:junit:4.12' already in dependencies

Add GitHub Actions CI workflow for automated APK builds and testing

The repo has .github/ISSUE_TEMPLATE/ configured but no CI/CD workflows. With minifyEnabled and signing configs already set up, adding a GitHub Action would automatically build and test PRs, catching build failures early. This is especially important given the complexity of multiple media player implementations and API level support (minSdkVersion 16 to targetSdkVersion 28).

  • [ ] Create .github/workflows/android-build.yml for Gradle builds on push/PR
  • [ ] Configure workflow to run 'gradlew build' for app module with caching for faster runs
  • [ ] Add step to run unit tests and generate coverage reports
  • [ ] Add conditional APK artifact upload for release builds
  • [ ] Reference existing signing config in app/build.gradle for automated builds

Create comprehensive feature documentation for CustomJzvd implementations in README

The repo has 9 custom Jzvd implementations (JzvdStdSpeed, JzvdStdTinyWindow, JzvdStdMp3, etc.) in app/src/main/java/cn/jzvd/demo/CustomJzvd/ but the README.md only mentions 'Highly customizable Android video framework' without explaining these concrete examples. Adding documentation with code examples for each custom implementation would lower contribution barriers and improve discoverability.

  • [ ] Add 'Custom UI Examples' section to README.md after existing content
  • [ ] Document JzvdStdSpeed with code snippet showing playback speed control
  • [ ] Document JzvdStdTinyWindow with example of floating window implementation
  • [ ] Document JzvdStdMp3 showing audio-only playback usage
  • [ ] Add a comparison table of all 9 CustomJzvd classes with their unique features
  • [ ] Link examples to corresponding source files in app/src/main/java/cn/jzvd/demo/CustomJzvd/

🌿Good first issues

  • Add unit tests for CustomMedia/JZMediaExo.java—currently no test file visible; test player state transitions (prepare, play, pause, release) with mock ExoPlayer
  • Update ijkplayer from 0.8.4 to latest with arm64-v8a and x86 architectures; verify backward compatibility with existing playback event handlers
  • Document the core jiaozivideoplayer module API (referenced in build.gradle but source not shown): create javadoc/wiki page listing Jzvd base class, required overrides, and event callbacks used by all demo activities

Top contributors

Click to expand

📝Recent commits

Click to expand
  • 3db479b — Update README.md (lipangit)
  • b20c9f9 — () (lipangit)
  • 5b07bcf — move to jzvd.org (lipangit)
  • 69a560f — upgrade as (lipangit)
  • 1cbae0b — add audio form (lipangit)
  • a0ccd90 — upgrade as (lipangit)
  • 4986bf6 — fix play bug (lipangit)
  • bf939bc — Merge tag 'v7.0.5' into develop (lipangit)
  • 8b8e153 — Merge branch 'release/v7.0.5' (lipangit)
  • ffa37f3 — v7.0.5 (lipangit)

🔒Security observations

  • Critical · Hardcoded Credentials in Build Configuration — app/build.gradle (signingConfigs.releaseConfig section). The app/build.gradle file contains hardcoded keystore credentials (storePassword: '123456' and keyPassword: '123456') in plain text. These credentials are used for signing the release APK and should never be committed to version control. This allows anyone with repository access to sign malicious APKs using the same key. Fix: Move credentials to a secure external configuration file (e.g., local.properties or gradle.properties in .gitignore). Use environment variables or a secrets management system for CI/CD pipelines. Consider using Android Studio's built-in keystore management.
  • High · Keystore File Committed to Repository — app/jzvd-keystore. The signing keystore file 'jzvd-keystore' is committed to the repository. Combined with hardcoded passwords, this compromises the entire signing key. An attacker can extract and reuse this key to sign malicious APKs that would be trusted by users. Fix: Remove the keystore file from version control immediately. Add it to .gitignore. Store the keystore file securely outside the repository and reference it via environment variables or CI/CD secrets management.
  • High · Outdated and Vulnerable Dependencies — app/build.gradle (dependencies section). The project uses several outdated dependencies with known vulnerabilities: ExoPlayer 2.9.1 (released 2019), Glide 4.7.1 (2018), and android-support libraries (deprecated). These versions contain multiple CVEs including security bypasses, denial of service, and information disclosure vulnerabilities. Fix: Update all dependencies to the latest stable versions: ExoPlayer to 2.18+, Glide to 4.15+, migrate from support libraries to AndroidX (androidx.appcompat:appcompat:1.6+). Run 'gradle dependencies --configuration releaseRuntimeClasspath' to identify vulnerable transitive dependencies.
  • High · Deprecated Android Support Libraries — app/build.gradle (dependencies: appcompat-v7:28.0.0, recyclerview-v7:28.0.0). The project relies on deprecated 'com.android.support' libraries (appcompat-v7, recyclerview-v7) which are no longer maintained. These libraries have reached end-of-life and will not receive security updates. Fix: Migrate to AndroidX equivalents: androidx.appcompat:appcompat and androidx.recyclerview:recyclerview. Use Android Gradle Plugin 3.0+ to automatically convert or manually update imports.
  • Medium · Low Minimum SDK Version — app/build.gradle (defaultConfig.minSdkVersion 16). minSdkVersion is set to 16 (Android 4.1, released 2012). This is over a decade old and lacks numerous security features including proper TLS 1.2+ support, cryptography improvements, and security patches. Fix: Increase minSdkVersion to at least 21 (Android 5.0) or preferably 24+. This eliminates exposure to numerous vulnerabilities and allows use of modern security APIs.
  • Medium · Weak Keystore Credentials — app/build.gradle and app/jzvd-keystore. The keystore password '123456' is extremely weak and easily guessable. Even ignoring the hardcoding issue, this password provides minimal protection if the keystore file is obtained. Fix: Use strong, randomly-generated passwords (minimum 20+ characters with mixed character types). Use Android Studio or keytool to regenerate the keystore with a strong password.
  • Medium · Lint Errors Not Enforced — app/build.gradle (lintOptions.abortOnError false). The build configuration disables lint error abort (abortOnError false), allowing the app to be built with lint-detected security and quality issues. This could hide potential vulnerabilities from developers. Fix: Set abortOnError to true to catch security and quality issues during builds. Address specific lint warnings rather than silencing them globally. Use lintOptions {} configuration to manage specific rules individually.
  • Medium · WebView Usage Without Security Review — undefined. The presence of ActivityWebView.java and assets/jzvd.html Fix: undefined

LLM-derived; treat as a starting point, not a security audit.


Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.

Mixed signals · lipangit/JiaoZiVideoPlayer — RepoPilot