콘텐츠로 건너뛰기
星罗
검색
언어 전환
뒤로 가기

미디어 플레이어

2분 분량 GitHub에서 편집

Xingluo는 APlayer(오디오)와 DPlayer(비디오)를 통합하며, Markdown 및 MDX에서 플레이어를 만드는 두 가지 방법을 지원하고 모두 지연 로드됩니다.

활성화

features.players에서 필요에 따라 각 플레이어를 전환하세요 xingluo.config.ts:

ts
features: { players: { aplayer: true, // APlayer 오디오 플레이어 활성화 dplayer: true, // DPlayer 비디오 플레이어 활성화 }, }

둘은 독립적입니다. 비활성화 시:

  • remarkPlayers 플러그인이 주입되지 않음(MD 펜스가 분석되지 않음)
  • 플레이어 클라이언트 스크립트가 로드되지 않음
  • 빌드 출력에 aplayer / dplayer 청크가 없음

두 가지 사용 모드

모드적용 대상구문
MD fence일반 .md 및 .mdx```aplayer / ```dplayer + JSON 구성 본문
MDX 컴포넌트.mdx만 해당import { APlayer, DPlayer } from "@/components/mdx"

두 모드 모두 최종적으로 동일한 플레이스홀더 div 구조(<div class="xng-aplayer|xng-dplayer" data-config>)를 출력하며, src/scripts/players.ts에 의해 지연 로드되고 인스턴스화됩니다.

APlayer 오디오 플레이어

MD 펜스

markdown
```aplayer { "audio": [ { "name": "Song", "artist": "Artist", "url": "/audio/song.mp3", "cover": "/images/cover.jpg", "lrc": "[00:00.00] First lyric line" } ], "theme": "#b7daff", "loop": "all", "autoplay": false } ```

MDX 컴포넌트

mdx
import { APlayer } from "@/components/mdx"; <APlayer audio={[ { name: "Song", artist: "Artist", url: "/audio/song.mp3", cover: "/images/cover.jpg", }, ]} theme="#b7daff" loop="all" />

옵션

| 필드 | 타입 | 기본값 | 설명 | | audio | Audio | Audio[] | 필수 | 오디오 객체 또는 목록 | | theme | string | #b7daff | 플레이어 테마 색상 | | loop | "all" | "one" | "none" | all | 반복 모드 | | order | "list" | "random" | list | 재생 순서 | | volume | number | 0.7 | 초기 볼륨 (0–1) | | autoplay | boolean | false | 자동 재생 (브라우저 정책에 따라 다름) | | listFolded | boolean | false | 목록 접기 | | listMaxHeight | string | — | 목록 최대 높이 (CSS 값) | | lrcType | 0 | 1 | 2 | 3 | 0 | 가사 유형: 0 없음 / 1 문자열 / 2 URL |

audio 객체

필드설명
name트랙 이름 (title로 폴백, 그 다음 '오디오 이름'으로 폴백)
artist아티스트 (author로 폴백)
url오디오 URL (필수)
cover커버 (pic으로 폴백)
lrc가사 (문자열 또는 URL, lrcType과 쌍을 이룸)
theme트랙별 테마 색상
type오디오 타입: auto | hls | normal

DPlayer 비디오 플레이어

MD 펜스

markdown
```dplayer { "video": { "url": "/videos/demo.mp4", "pic": "/images/video-cover.jpg", "type": "auto" }, "theme": "#b7daff", "autoplay": false, "loop": false } ```

MDX 컴포넌트

mdx
import { DPlayer } from "@/components/mdx"; <DPlayer video={{ url: "/videos/demo.mp4", pic: "/images/video-cover.jpg" }} theme="#b7daff" subtitle={{ url: "/subtitles.vtt", type: "webvtt" }} />

옵션

필드타입기본값설명
videoVideo필수비디오 설정
themestring#b7daff테마 색상
autoplaybooleanfalse자동 재생
loopbooleanfalse반복 재생
screenshotbooleanfalse스크린샷 기능
hotkeybooleantrue단축키
preload"none" | "metadata" | "auto"auto사전 로드
volumenumber0.7초기 볼륨
playbackSpeednumber[]—재생 속도 목록
subtitleSubtitle—자막
danmakuDanmaku—단마쿠 (탄막 댓글)
livebooleanfalse라이브 모드
mutexbooleantrue뮤텍스 (페이지당 한 플레이어만)

video 객체

필드설명
url비디오 URL (필수)
pic커버
thumbnails썸네일 URL
type비디오 타입: auto | hls | flv | dash | normal
quality품질 목록 + defaultQuality 인덱스

subtitle 객체

필드설명
url자막 URL (필수)
typewebvtt | ass
fontSize글꼴 크기
bottom아래로부터의 거리
color색상

danmaku 객체

필드설명
id고유 단마쿠 풀 ID (필수)
api단마쿠 API URL (필수)
user사용자 식별자
maximum최대 단마쿠 수

지연 로딩 메커니즘

플레이어는 IntersectionObserver를 통해 지연 로딩됩니다: 플레이스홀더 div가 뷰포트의 200px 이내에 들어올 때만 플레이어 모듈과 스타일을 동적으로 import하고 인스턴스화합니다.

  • APlayer: 동적 import("aplayer") + import("aplayer/dist/APlayer.min.css")
  • DPlayer: 동적 import("dplayer") (스타일은 JS에 인라인됨; 별도 CSS 불필요)

모듈 로딩은 공유 Promise 캐시를 사용하여 반복된 동적 임포트를 방지합니다. 재인스턴스화는 dataset 마커(xng-init, xng-observed)를 통해 방지됩니다.

View Transitions 적응

플레이어 스크립트는 astro:page-load를 수신하고 각 페이지 로드 후 플레이스홀더 div를 다시 스캔합니다. View Transitions 페이지 전환 후, 새 페이지의 플레이어 플레이스홀더가 다시 관찰되고 지연 로딩됩니다.

성능

  • 플레이어 비활성화 시 번들 제로(remark 플러그인이 주입되지 않고 클라이언트 스크립트가 로드되지 않음)
  • 활성화되어도 페이지에 플레이어가 없으면 런타임 제로(스크립트는 로드되지만 인스턴스화하지 않음)
  • 플레이어 모듈은 독립 청크로, 사용하는 페이지에서만 필요 시 로드
  • CSS와 JS는 별도로 임포트되어 인스턴스화 전에 스타일이 준비됨을 보장

타입 선언

APlayer와 DPlayer는 공식 TypeScript 타입이 없습니다. Xingluo는 src/types/aplayer.d.ts 및 src/types/dplayer.d.ts에 느슨한 모듈 선언을 제공하며, 스프레드 호환성을 위해 옵션 필드는 선택 사항으로 설정됩니다. MDX 컴포넌트 Props는 완전한 타입 제약 조건을 가집니다.


관련 글

  • 배포

    1분 분량

    Xingluo 배포 가이드 - 정적 호스팅 플랫폼(Netlify/Vercel/GitHub Pages), Nginx 자체 호스팅, Docker 및 환경 변수.

  • 검색

    1분 분량

    Xingluo 검색 가이드 - Flexsearch 전체 텍스트 검색 통합, 인덱스 생성, UI, 다국어 검색 및 성능.