Actions
개발계획서¶
BBPlayer 개발계획서¶
| 항목 | 내용 |
|---|---|
| 프로젝트명 | BBPlayer |
| 프로그램명 | BBPlayer |
| 문서 버전 | v4.22 |
| 작성일 | 2026년 03월 25일 |
| 작성자 | 페후 (이태훈) |
| 상태 | 진행 중 (In Progress) |
1. 개발 목표¶
기존 동영상 플레이어의 자막 오류 및 소리 문제를 개선하고, Windows 데스크탑과 Android 모바일 환경을 모두 지원하는 크로스플랫폼 동영상 플레이어 *BBPlayer*를 개발한다.
2. 개발 환경¶
| 구분 | 내용 |
|---|---|
| 개발 언어 | Dart |
| 프레임워크 | Flutter |
| 타겟 플랫폼 | Windows 10 이상 (64bit), Android 8.0 (API 26) 이상, macOS |
| 미디어 엔진 | media_kit (FFmpeg 기반) |
| 로컬 DB | sqflite (SQLite) |
| 윈도우 관리 | window_manager |
| 앱 아이콘 | flutter_launcher_icons (BBPlayerIcon.png 기반 자동 생성) |
| IDE | Android Studio / VS Code |
3. 기능별 개발계획¶
Phase 1 — 핵심 재생 기능¶
목표: 앱 실행 후 영상 파일을 열고 기본 재생이 가능한 상태
3.1.1 파일 열기 (FR 연관: FR-17, Ctrl+O) ✅ 완료¶
| 항목 | 내용 |
|---|---|
| 기능 | file_picker를 통해 파일 탐색기에서 영상 파일 선택 및 로드 |
| 지원 포맷 | MP4, MKV, AVI, MOV, FLV, WMV |
| 플랫폼 | Windows / Android / macOS |
| 구현 포인트 | file_picker 패키지 연동, media_kit Player에 파일 경로 전달 |
| 완료 조건 | 파일 선택 후 2초 이내 재생 시작 |
| 완료일 | 2026-03-24 |
| 비고 | Windows 정상 동작 확인 |
3.1.2 재생 / 일시정지 (FR-01) ✅ 완료¶
| 항목 | 내용 |
|---|---|
| 기능 | 컨트롤 바 버튼 및 단축키(Space)로 재생/일시정지 토글 |
| 플랫폼 | Windows / Android / macOS |
| 구현 포인트 | media_kit Player.playOrPause() 연동, 중앙 아이콘 애니메이션 피드백 |
| 완료 조건 | 버튼 및 Space 키 입력 시 즉각 토글 동작 |
| 완료일 | 2026-03-24 |
| 비고 | 화면 탭/클릭 토글, 재생 중 3초 후 컨트롤 자동 숨김, 마우스 이동 시 컨트롤 재표시 추가, 컨트롤 수동 숨김 토글 추가 (Windows/macOS: H키, Android: 상단 바 숨김 버튼) |
3.1.3 재생 진행바 (FR-03) ✅ 완료¶
| 항목 | 내용 |
|---|---|
| 기능 | 전체 길이 대비 현재 위치 표시, 드래그로 탐색 |
| 플랫폼 | Windows / Android / macOS |
| 구현 포인트 | VideoController position stream 구독, Slider 위젯 연동, seek() 호출 |
| 완료 조건 | 드래그 탐색 후 0.5초 이내 화면 반영 |
| 완료일 | 2026-03-24 |
| 비고 | 드래그 중 위치 떨림 방지 (_isDragging 상태 분리), 드래그 중 파란색 시간 툴팁 표시, 드래그 중 자동 숨김 타이머 정지, 방향키 탐색 시 일시정지→seek→재생 동작 추가, 연속 입력 시 누적 이동량 표시 (→ 10초 / Shift+→ 30초), 방향키 입력 시 진행바 즉각 반영 (_seekPreviewPos로 디바운스 전 시각적 위치 업데이트) |
3.1.4 볼륨 조절 / 음소거 (FR-14, FR-15) ✅ 완료¶
| 항목 | 내용 |
|---|---|
| 기능 | 0~100% 슬라이더 조절, 음소거 토글 및 이전 볼륨 복원 |
| 플랫폼 | Windows / Android / macOS |
| 구현 포인트 | Player.setVolume(), 음소거 전 볼륨 상태 로컬 변수 보존 |
| 단축키 | ↑/↓ (5% 단위), M (음소거) |
| 완료 조건 | 슬라이더 및 단축키 모두 정상 동작 |
| 완료일 | 2026-03-24 |
| 비고 | 컨트롤 바 내 볼륨 슬라이더 + 음소거 버튼 추가, 볼륨 변경 시 우측 상단 오버레이 표시 (2초 후 자동 숨김), 음소거 해제 시 이전 볼륨 복원 |
3.1.5 전체화면 토글 (FR-05) ✅ 완료¶
| 항목 | 내용 |
|---|---|
| 기능 | 전체화면 진입 및 해제 |
| 플랫폼 | Windows / Android / macOS |
| 구현 포인트 | window_manager (Windows/macOS), SystemChrome.setEnabledSystemUIMode (Android) |
| 단축키 | F / F11 (토글), Esc (전체화면 해제 → 이미 해제 상태면 뒤로가기) |
| 완료 조건 | 전체화면 진입/해제 시 정상 동작 |
| 완료일 | 2026-03-24 |
| 비고 | 상단 바 전체화면 버튼 추가, 플레이어 종료 시 전체화면 자동 해제 |
Phase 2 — 자막 & 오디오¶
목표: 외부 자막 파일 적용 및 다중 오디오 트랙 선택
3.2.1 자막 파일 불러오기 (FR-09) ✅ 완료¶
| 항목 | 내용 |
|---|---|
| 기능 | SRT / ASS 형식의 외부 자막 파일 자동 로드 + 수동 로드 |
| 플랫폼 | Windows / Android / macOS |
| 구현 포인트 | file_picker로 자막 파일 경로 선택, subtitle_view 패키지 파싱 |
| 완료 조건 | 자막 선택 즉시 영상 위에 정상 표시 |
- 재생 시작 시 영상 파일과 동일 폴더 내 동일 이름의 자막 파일(
.srt,.ass,.ssa) 자동 탐색 - 자막 파일 발견 시 알림 없이 즉시 적용
- 우선순위:
.srt→.ass→.ssa
- 컨트롤 바 자막 버튼 또는 단축키(
S길게 누르기)로 파일 탐색기 열기 - 수동 로드 시 자동 로드된 자막을 덮어씀
| 완료일 | 비고 |
|---|---|
| 2026-03-24 | media_kit SubtitleTrack.uri() 활용, 자막 버튼 파란색(활성)/회색(비활성) 표시, 하단에 자막 파일명 표시, S키 ON/OFF 토글 (자막 없으면 파일 탐색기 오픈) |
3.2.2 자막 싱크 조절 (FR-10) ✅ 완료¶
| 항목 | 내용 |
|---|---|
| 기능 | 자막 표시 시간을 ±0.1초 단위로 수동 조정 |
| 플랫폼 | Windows / Android / macOS |
| 구현 포인트 | SubtitleService.applySrtOffset()으로 SRT 타임스탬프 재파싱 → 임시 파일 저장 → media_kit 재로드 |
| 단축키 | [ (-0.1s) / ] (+0.1s) |
| 완료 조건 | 조절 즉시 자막 타이밍에 반영 |
| 완료일 | 2026-03-24 |
| 비고 | SRT 전용 오프셋 처리, 좌측 상단 싱크 오버레이 3초 표시, 하단 자막 바에 ±0.1s 버튼 및 현재 오프셋 표시, 새 자막 로드 시 오프셋 0으로 초기화 |
3.2.3 자막 ON/OFF (FR-11) ✅ 완료¶
| 항목 | 내용 |
|---|---|
| 기능 | 자막 표시 여부 즉시 토글 |
| 플랫폼 | Windows / Android / macOS |
| 단축키 | S |
| 완료 조건 | 토글 즉시 자막 표시/숨김 전환 |
| 완료일 | 2026-03-24 |
| 비고 | 3.2.1 구현 시 함께 완료. SubtitleTrack.no()로 OFF, SubtitleTrack.uri()로 ON, 자막 없으면 S키가 파일 탐색기 오픈으로 동작 |
3.2.4 자막 스타일 커스터마이징 (FR-12) ✅ 완료¶
| 항목 | 내용 |
|---|---|
| 기능 | 자막 글자 크기, 색상, 배경색 사용자 설정 |
| 플랫폼 | Windows / Android / macOS |
| 구현 포인트 | SubtitleViewConfiguration으로 TextStyle 적용, 설정 패널 오버레이, sqflite settings 테이블에 저장/복원 |
| 완료 조건 | 설정 변경 즉시 자막에 반영, 앱 재실행 후에도 유지 |
| 완료일 | 2026-03-24 |
| 비고 | 글자 크기 4단계(소22/중32/대44/특대56), 글자 색상 4종(흰색/노란색/하늘색/연두색), 배경 3종(없음/반투명/불투명). 상단 바 자막 스타일 버튼(Aa)으로 패널 토글. DatabaseService에 getSetting/setSetting 추가 |
3.2.5 오디오 트랙 선택 (FR-16) ✅ 완료¶
| 항목 | 내용 |
|---|---|
| 기능 | 다중 오디오 트랙(MKV 등)에서 원하는 트랙 선택 |
| 플랫폼 | Windows / Android / macOS |
| 구현 포인트 | _player.stream.tracks / _player.stream.track 구독, _player.setAudioTrack() 호출 |
| 완료 조건 | 트랙 목록 표시 및 선택 후 즉시 오디오 전환 |
| 완료일 | 2026-03-24 |
| 비고 | 트랙 2개 이상일 때만 하단 바 오디오 버튼 표시. 트랙명/언어 코드 표시, 현재 선택 트랙 강조. 우측 하단 패널 오버레이로 목록 표시 |
Phase 3 — 플레이리스트¶
목표: 여러 파일을 연속 재생하고 재생 이력을 관리
3.3.1 플레이리스트 파일 추가 (FR-17) ✅ 완료¶
| 항목 | 내용 |
|---|---|
| 기능 | 파일 탐색기로 개별 파일 또는 폴더 단위 영상 추가 |
| 플랫폼 | Windows / Android / macOS |
| 구현 포인트 | file_picker 다중 선택 / getDirectoryPath + dart:io Directory.list() 스캔 |
| 완료 조건 | 선택한 파일/폴더 내 영상이 플레이리스트에 정상 추가 |
| 완료일 | 2026-03-24 |
| 비고 | PlayerScreen이 playlist + initialIndex를 받는 구조로 변경. 홈/플레이어 모두에서 파일/폴더 추가 가능. 우측 슬라이드 패널로 목록 표시, L키/상단 버튼으로 토글. 항목 탭으로 즉시 전환, X버튼으로 삭제. 폴더 추가 시 알파벳순 정렬 |
3.3.2 이전 / 다음 영상 이동 (FR-19) ✅ 완료¶
| 항목 | 내용 |
|---|---|
| 기능 | 플레이리스트 내 이전/다음 영상으로 이동 |
| 플랫폼 | Windows / Android / macOS |
| 단축키 | N (다음), P (이전) |
| 완료 조건 | 버튼 및 단축키로 정상 이동 |
| 완료일 | 2026-03-24 |
| 비고 | 영상 종료 시 자동으로 다음 영상 재생 (마지막 항목이면 정지 유지). P키는 3초 이내면 처음으로 되감기, 이후면 이전 영상 이동. 플레이리스트 2개 이상일 때만 이전/다음 버튼 표시. 마지막 항목에서 N키 수동 조작 시 처음으로 순환 |
3.3.3 반복 재생 모드 (FR-20) ✅ 완료¶
| 항목 | 내용 |
|---|---|
| 기능 | 전체 반복 / 한 곡 반복 / 셔플 모드 선택 |
| 플랫폼 | Windows / Android / macOS |
| 구현 포인트 | RepeatMode enum (none/all/one), _isShuffle bool, _playNext 내 분기 처리 |
| 완료 조건 | 모드 전환 후 재생 순서에 즉시 반영 |
| 완료일 | 2026-03-24 |
| 비고 | R키로 반복 모드 순환 (없음→전체→한 곡). 셔플은 버튼 전용. 한 곡 반복 시 seek(0)+play로 재시작. 셔플+이전 이동도 랜덤 인덱스 적용. 반복/셔플 활성화 시 버튼 파란색 강조 |
3.3.4 이어보기 (FR-07) ✅ 완료¶
| 항목 | 내용 |
|---|---|
| 기능 | 앱 종료 후 재실행 시 마지막 재생 위치부터 자동 이어 재생 |
| 플랫폼 | Windows / Android / macOS |
| 구현 포인트 | sqflite play_history 테이블에 저장/복원, WidgetsBindingObserver로 백그라운드 전환 감지, 5초 주기 자동 저장 |
| 완료 조건 | 재실행 후 이전 위치에서 자동 재개 |
| 완료일 | 2026-03-24 |
| 비고 | 저장 시점 3단계: ① 재생 중 5초 주기 자동 저장 ② 백그라운드/비활성 전환 시 즉시 저장 (AppLifecycleState) ③ dispose(화면 이탈) 시 저장. 복원은 _initPlayback()에서 getLastPosition() 후 seek() |
3.3.5 최근 재생 목록 (FR-21) ✅ 완료¶
| 항목 | 내용 |
|---|---|
| 기능 | 최근 재생 파일 히스토리 저장 및 빠른 열기 |
| 플랫폼 | Windows / Android / macOS |
| 구현 포인트 | sqflite play_history 테이블, 홈 화면 ListView, Dismissible 스와이프 삭제, 전체 삭제 |
| 완료 조건 | 목록에서 항목 선택 시 해당 파일 즉시 재생 |
| 완료일 | 2026-03-24 |
| 비고 | 홈 화면 목록에 항목 수 표시. 좌로 스와이프 → 개별 삭제. 앱 바 휴지통 버튼 → 전체 삭제 (확인 다이얼로그). DatabaseService에 deleteHistory / clearAllHistory 메서드 추가 |
Phase 4 — 편의 기능¶
목표: 생산성과 사용 편의성을 높이는 고급 조작 기능
3.4.1 앞/뒤로 이동 (FR-02) ✅ 완료¶
| 항목 | 내용 |
|---|---|
| 기능 | 단축키로 현재 위치에서 이동 |
| 플랫폼 | Windows / Android / macOS |
| 단축키 | →/← (±10초), Shift+→/← (±30초) |
| 완료 조건 | 정확한 시간 이동, 연속 입력 시 누적 반영 |
| 완료일 | 2026-03-24 |
| 비고 | 3.1.3 구현 시 함께 완료. _arrowSeek()로 누적 후 400ms 디바운스, 일시정지→seek→재생 동작. 중앙 피드백 아이콘 + 누적량 표시 |
3.4.2 재생 속도 조절 (FR-04) ✅ 완료¶
| 항목 | 내용 |
|---|---|
| 기능 | 0.25x ~ 2.0x 범위 (0.25x 단위) 속도 선택 |
| 플랫폼 | Windows / Android / macOS |
| 구현 포인트 | Player.setRate() 호출, 하단 바 속도 버튼 + 중앙 팝업 패널 |
| 완료 조건 | 속도 변경 즉시 재생에 반영 |
| 완료일 | 2026-03-24 |
| 비고 | 0.25/0.5/0.75/1.0/1.25/1.5/1.75/2.0x 8단계. 하단 바 속도 버튼(1.0x 표시, 1.0x 아닐 때 파란색 강조). < / > 키로 단계 조절. 선택 즉시 패널 닫힘 |
3.4.3 A-B 구간 반복 (FR-08) ✅ 완료¶
| 항목 | 내용 |
|---|---|
| 기능 | A(시작점)와 B(종료점) 지정 후 해당 구간 무한 반복 |
| 플랫폼 | Windows / Android / macOS |
| 단축키 | A (1회: A 설정, 2회: B 설정+반복 시작, 3회: 해제) |
| 구현 포인트 | position stream에서 B 도달 시 A로 seek(), 진행바에 A/B 마커 표시 |
| 완료 조건 | A-B 구간 정확히 반복, 해제 시 정상 종료 |
| 완료일 | 2026-03-24 |
| 비고 | A보다 앞에서 B 설정 시 A 재설정. 진행바 위 녹색(A)/빨간색(B) 수직 마커. 하단 A↔B 상태 표시줄 + X 버튼 해제. 파일 교체 시 자동 초기화 |
3.4.4 항상 위 (Always on Top) (FR-06) ✅ 완료¶
| 항목 | 내용 |
|---|---|
| 기능 | 플레이어 창을 항상 최상위로 표시 |
| 플랫폼 | Windows / macOS (window_manager 지원 데스크탑 전용) |
| 구현 포인트 | windowManager.setAlwaysOnTop() 호출, T키 단축키, 상단 핀 버튼 |
| 완료 조건 | 토글 시 창 최상위/일반 전환 정상 동작 |
| 완료일 | 2026-03-24 |
| 비고 | T키 단축키, 상단 바 핀 아이콘 버튼 (활성 시 파란색). Android에서는 버튼 미표시. 플레이어 종료 시 자동 해제 |
3.4.5 키보드 단축키 전체 구현 + 도움말 오버레이 (FR 연관: 2.6절) ✅ 완료¶
| 항목 | 내용 |
|---|---|
| 기능 | Space, 방향키 (±10초 / Shift ±30초), F/F11, Esc, M, S, [, ], H, ? 단축키 전체 지원 + 도움말 오버레이 |
| 플랫폼 | Windows / macOS / Android (도움말 버튼은 전 플랫폼 공통) |
| 구현 포인트 | HardwareKeyboard API 활용, ? 키 또는 상단 바 버튼으로 오버레이 토글 |
| 도움말 내용 | Space(재생/정지), →/←(±10초), Shift+→/←(±30초), ↑/↓(볼륨), M(음소거), S(자막), [/](자막 싱크), F/F11, H(컨트롤 숨김), ?(도움말) |
| 완료 조건 | 모든 단축키 정상 동작, 도움말 오버레이 표시/숨김 정상 동작 |
| 완료일 | 2026-03-24 |
3.4.7 재생 중 파일 교체 ✅ 완료 (Windows/macOS 전용)¶
| 항목 | 내용 |
|---|---|
| 기능 | 재생 중 현재 파일을 다른 파일로 즉시 교체 |
| 플랫폼 | Windows / macOS (Android 제외 — 외부 앱 인텐트 실행 방식으로 불필요) |
| 방식 1 | 플레이어 상단 바 파일 열기 버튼 → file_picker로 새 파일 선택 → 즉시 교체 재생 |
| 방식 2 | 드래그 앤 드롭으로 플레이어 화면에 파일 드롭 → 즉시 교체 재생 (3.5.4와 연계) |
| 구현 포인트 | 교체 시 자막 오프셋 초기화, 재생 위치 초기화, 이전 파일 히스토리 저장 후 신규 파일 재생 |
| 완료 조건 | 버튼 및 드래그 앤 드롭으로 파일 교체 후 즉시 재생 |
| 완료일 | 2026-03-25 |
| 비고 | 파일 경로는 _currentFilePath로 추적. Android는 DS File 등 외부 앱에서 인텐트로 직접 실행하는 패턴으로 재생 중 파일 교체 기능 제외 |
3.4.6 터치 제스처 제어 (Android 전용, FR 연관: 2.5절) ✅ 완료¶
| 항목 | 내용 |
|---|---|
| 기능 | 스와이프로 탐색/밝기/볼륨 조절, 탭으로 컨트롤 토글, 더블탭으로 ±10초 |
| 플랫폼 | Android 전용 |
| 구현 포인트 | GestureDetector, screen_brightness 패키지 활용, 제스처 영역 분할 |
| 제스처 상세 | 단일 탭: 컨트롤 표시/숨김 / 더블탭 왼쪽: -10초 / 더블탭 오른쪽: +10초 / 수직 스와이프 왼쪽 절반: 밝기 / 수직 스와이프 오른쪽 절반: 볼륨 / 수평 스와이프: 탐색 (스크린 가로폭 100% = 180초) |
| 오버레이 | 제스처 동작 중 화면 중앙에 아이콘 + 수치 표시, 2초 후 자동 소멸 |
| 완료 조건 | 모든 제스처 방향 및 영역별 동작 정상 |
| 완료일 | 2026-03-24 |
3.4.9 비디오 프레임 캡처 ✅ 완료¶
| 항목 | 내용 |
|---|---|
| 기능 | 현재 재생 중인 비디오 프레임을 UI 없이 순수 영상만 캡처하여 저장 |
| 플랫폼 | Windows / Android / macOS |
| 구현 포인트 | player.screenshot() (media_kit 내장, libmpv 디코더에서 직접 추출) → gal 패키지로 저장 |
| 저장 위치 | Android: 갤러리(BBPlayer 앨범) / Windows: Pictures\BBPlayer\ / macOS: 사진 앱 |
| 트리거 | 상단 바 카메라 버튼 또는 C 단축키 |
| 피드백 | 저장 성공/실패 오버레이 2초 표시 |
| 완료 조건 | 버튼/단축키 → 순수 영상 프레임 저장 확인 |
| 완료일 | 2026-03-24 |
| 비고 | Flutter UI 미포함. gal 패키지 추가, Android WRITE_EXTERNAL_STORAGE 권한 추가(maxSdkVersion=29) |
3.4.8 외부 앱에서 동영상 파일 열기 (Android 인텐트) ✅ 완료¶
| 항목 | 내용 |
|---|---|
| 기능 | 파일 매니저 등 외부 앱에서 동영상 파일을 선택 시 BBPlayer가 앱 선택 목록에 표시되고, 선택 시 즉시 재생 |
| 플랫폼 | Android 전용 |
| 구현 포인트 | AndroidManifest.xml에 ACTION_VIEW + video/* intent-filter 추가, MainActivity에 MethodChannel(초기 실행) + EventChannel(실행 중 수신) 구현 |
| URI 처리 | content:// URI는 MediaStore를 통해 실제 파일 경로로 변환 시도, 실패 시 URI 그대로 media_kit에 전달 |
| 완료 조건 | 파일 매니저에서 동영상 탭 → 앱 선택 목록에 BBPlayer 표시 → 선택 시 즉시 재생 |
| 완료일 | 2026-03-24 |
| 비고 | intent-filter에 content:// scheme 명시 및 BROWSABLE 카테고리 추가, http/https scheme 추가로 DS File 등 NAS 스트리밍 앱에서도 BBPlayer 선택 가능 |
Phase 5 — 고급 기능¶
목표: 사용자 경험을 극대화하는 부가 기능
3.5.1 진행바 썸네일 미리보기 (FR-22) ✅ 완료¶
| 항목 | 내용 |
|---|---|
| 기능 | 진행바에 마우스 오버 시 해당 위치의 썸네일 팝업 표시 |
| 플랫폼 | Windows / macOS (마우스 입력 가능 데스크탑 전용) |
| 구현 포인트 | 별도 Player 인스턴스(_thumbPlayer)로 메인 재생 중단 없이 프레임 seek → screenshot() → Image.memory() 팝업 표시, 150ms 디바운스, 드래그 중 숨김 |
| 완료 조건 | 마우스 위치에 따라 정확한 썸네일 표시 |
3.5.2 자막 자동 검색 (FR-13) ❌ 취소¶
| 항목 | 내용 |
|---|---|
| 기능 | 재생 중 파일명 기준으로 외부 자막 사이트 검색 및 다운로드 제안 |
| 플랫폼 | Windows / Android / macOS |
| 구현 포인트 | 자막 API 연동 (OpenSubtitles 등), HTTP 요청, 다운로드 후 자동 적용 |
| 완료 조건 | 검색 결과 목록 표시 및 선택한 자막 자동 적용 |
❌ 취소 사유: 사용 빈도 낮고 외부 API 의존성 및 유지보수 부담 대비 실용성 부족. 필요 시 자막 파일을 영상과 동일 폴더에 배치하는 기존 자동 로드 방식으로 대체 가능.
3.5.3 PIP (Picture in Picture) (FR-23) ✅ 완료¶
| 항목 | 내용 |
|---|---|
| 기능 | 다른 앱 사용 중 영상을 작은 플로팅 창으로 재생 |
| 플랫폼 | Android 전용 (API 26 이상) |
| 구현 포인트 | AndroidManifest supportsPictureInPicture="true", MainActivity PIP MethodChannel + PIP 상태 EventChannel, Flutter에서 영상 비율로 PictureInPictureParams 전달 |
| PIP 진입 | 상단 바 PIP 버튼 탭 → enterPictureInPictureMode() 호출 |
| PIP 중 동작 | 컨트롤 전체 숨김, 영상만 표시, 재생 유지 |
| PIP 해제 | 창 확대 시 자동으로 컨트롤 복원 |
| 완료 조건 | PIP 진입/해제 및 영상 재생 정상 동작 |
| 완료일 | 2026-03-24 |
3.5.4 드래그 앤 드롭 (FR-18) ✅ 완료¶
| 항목 | 내용 |
|---|---|
| 기능 | 파일 탐색기에서 드래그하여 파일 추가 또는 교체 |
| 플랫폼 | Windows / macOS (desktop_drop 데스크탑 전용) |
| 동작 구분 | 플레이어 화면에 드롭 → 현재 파일 즉시 교체 (3.4.7 연계) / 플레이리스트에 드롭 → 목록에 추가 |
| 구현 포인트 | desktop_drop 패키지, DropTarget으로 전체 화면 래핑, detail.localPosition.dx로 드롭 위치 판별, 드래그 중 영역별 오버레이 UI 표시 |
| 완료 조건 | 드롭 위치에 따른 교체/추가 동작 정상 처리 |
| 완료일 | 2026-03-25 |
4. 데이터 설계¶
4.1 로컬 DB 테이블 (sqflite)¶
play_history (최근 재생 / 이어보기)¶
| 컬럼 | 타입 | 설명 |
|---|---|---|
| id | INTEGER PK | 자동 증가 |
| file_path | TEXT | 영상 파일 경로 |
| last_position | INTEGER | 마지막 재생 위치 (밀리초) |
| played_at | TEXT | 마지막 재생 일시 (ISO8601) |
settings (앱 설정)¶
| 컬럼 | 타입 | 설명 |
|---|---|---|
| key | TEXT PK | 설정 키 |
| value | TEXT | 설정 값 |
설정 항목 예시: subtitle_font_size, subtitle_color, subtitle_bg_color, theme_mode, volume
5. 개발 일정¶
| Phase | 기능 | 예상 기간 | 상태 |
|---|---|---|---|
| Phase 1 | 핵심 재생 기능 (파일 열기, 재생/정지, 진행바, 볼륨, 전체화면) | 2주 | ✅ 완료 |
| Phase 2 | 자막 & 오디오 (자막 로드, 싱크, 스타일, 오디오 트랙) | 2주 | ✅ 완료 |
| Phase 3 | 플레이리스트 (파일 추가, 이전/다음, 반복, 이어보기, 최근 목록) | 2주 | ✅ 완료 |
| Phase 4 | 편의 기능 (A-B 반복, 속도 조절, 단축키, 제스처, Always on Top) | 2주 | ✅ 완료 |
| Phase 5 | 고급 기능 (썸네일 미리보기, 자막 자동 검색, PIP, 드래그 앤 드롭) | 3주 | ✅ 완료 |
| 통합 테스트 | Windows / Android / macOS 전 기능 검증 및 버그 수정 | 1주 | 대기 |
| 합계 | 약 12주 |
6. 리스크 및 대응 방안¶
| 리스크 | 대응 방안 |
|---|---|
| media_kit Windows/Android 코덱 호환 이슈 | FFmpeg 빌드 플래그 확인, 포맷별 테스트 케이스 작성 |
| 자막 싱크 정확도 저하 | subtitle_view 파싱 로직 직접 오프셋 처리, 단위 테스트 작성 |
| Android PIP API 버전 파편화 | API 26 이상 조건부 활성화, 구버전 graceful fallback 처리 |
| 썸네일 추출 성능 저하 | 백그라운드 Isolate에서 추출, LRU 캐시 적용 |
| 자막 자동 검색 외부 API 변경 | API 추상화 레이어 설계, 복수 자막 소스 지원 |
7. 변경 이력¶
| 버전 | 일자 | 작성자 | 변경 내용 |
|---|---|---|---|
| v1.0 | 2026-03-24 | 페후 (이태훈) | 최초 작성 |
| v1.1 | 2026-03-24 | 페후 (이태훈) | 타겟 플랫폼 macOS 추가, 3.1.1 파일 열기 완료 처리 |
| v1.2 | 2026-03-24 | 페후 (이태훈) | 3.1.2 재생/일시정지 완료 처리 |
| v1.3 | 2026-03-24 | 페후 (이태훈) | 3.1.3 재생 진행바 완료 처리 |
| v1.4 | 2026-03-24 | 페후 (이태훈) | 방향키 이동 10초로 변경, Shift+방향키 30초 추가, 탐색 시 일시정지→seek→재생 동작 추가, 연속 입력 누적 표시 추가 |
| v1.5 | 2026-03-24 | 페후 (이태훈) | 3.1.4 볼륨 조절/음소거 완료 처리 |
| v1.6 | 2026-03-24 | 페후 (이태훈) | 3.1.5 전체화면 토글 완료 처리, window_manager 패키지 추가, Phase 1 전체 완료 |
| v1.7 | 2026-03-24 | 페후 (이태훈) | 앱 타이틀 BBPlayer로 통일 (macOS AppInfo.xcconfig 수정), flutter_launcher_icons로 전 플랫폼 아이콘 자동 생성 적용 |
| v1.8 | 2026-03-24 | 페후 (이태훈) | 3.2.1 자막 불러오기에 자동 로드 기능 추가 (동일 이름 자막 자동 탐색 및 적용, 수동 로드와 병행) |
| v1.9 | 2026-03-24 | 페후 (이태훈) | 3.2.1 자막 불러오기 구현 완료 (자동/수동 로드, 자막 버튼, 파일명 표시, S키 토글) |
| v2.0 | 2026-03-24 | 페후 (이태훈) | 3.2.2 자막 싱크 조절 구현 완료 (SubtitleService SRT 파싱, [ / ] 단축키, ±0.1s 버튼, 싱크 오버레이) |
| v2.1 | 2026-03-24 | 페후 (이태훈) | 3.2.3 자막 ON/OFF 완료 처리 (3.2.1 구현 시 이미 포함됨 확인) |
| v2.2 | 2026-03-24 | 페후 (이태훈) | 3.4.5에 단축키 도움말 오버레이 추가 (? 키 / 상단 키보드 버튼, 전체 단축키 테이블 표시, 외부 탭으로 닫기) |
| v2.3 | 2026-03-24 | 페후 (이태훈) | 3.4.7 재생 중 파일 교체 신규 항목 추가 (버튼 방식 + 드래그 앤 드롭 방식), 3.5.4 드래그 앤 드롭 드롭 위치별 동작 분기 내용 추가 |
| v2.4 | 2026-03-24 | 페후 (이태훈) | 3.4.7 파일 열기 버튼 방식 구현 완료 (플레이어 상단 바 폴더 버튼, 히스토리 저장 후 새 파일 교체, 자막/오프셋 초기화) |
| v2.5 | 2026-03-24 | 페후 (이태훈) | 3.4.7 버그 수정 — 파일 교체 시 중단 시점 저장 경로 오류 수정 (widget.filePath → _currentFilePath, 2회 이상 교체 시 이전 파일 위치가 원본 경로로 잘못 저장되던 문제 해결) |
| v2.6 | 2026-03-24 | 페후 (이태훈) | 3.2.4 자막 스타일 커스터마이징 구현 완료 (크기 4단계, 색상 4종, 배경 3종, 설정 DB 저장/복원, DatabaseService getSetting/setSetting 추가) |
| v2.7 | 2026-03-24 | 페후 (이태훈) | 3.2.5 오디오 트랙 선택 구현 완료 (tracks/track 스트림 구독, 트랙 2개 이상 시 버튼 표시, 우측 하단 패널, 선택 즉시 전환) |
| v2.8 | 2026-03-24 | 페후 (이태훈) | 3.3.1 플레이리스트 파일 추가 구현 완료 (PlayerScreen playlist 구조 변경, 홈 화면 다중 파일/폴더 선택, 플레이어 우측 패널, L키 단축키) |
| v2.9 | 2026-03-24 | 페후 (이태훈) | 3.3.2 이전/다음 영상 이동 구현 완료 (N/P 단축키, 이전/다음 버튼, 영상 종료 자동 다음 재생, P키 3초 룰) |
| v3.0 | 2026-03-24 | 페후 (이태훈) | 3.3.3 반복 재생 모드 구현 완료 (RepeatMode enum, 셔플, R키 단축키, 반복/셔플 버튼) |
| v3.1 | 2026-03-24 | 페후 (이태훈) | 3.3.4 이어보기 강화 — 5초 자동 저장 타이머, AppLifecycleState 백그라운드 저장, WidgetsBindingObserver 추가 |
| v3.2 | 2026-03-24 | 페후 (이태훈) | 3.3.5 최근 재생 목록 완료 — 스와이프 개별 삭제, 전체 삭제 확인 다이얼로그, 항목 수 표시, DatabaseService deleteHistory/clearAllHistory 추가 |
| v3.3 | 2026-03-24 | 페후 (이태훈) | 3.4.1 완료 처리 (3.1.3 구현 시 이미 포함됨 확인) |
| v3.4 | 2026-03-24 | 페후 (이태훈) | 3.4.2 재생 속도 조절 구현 완료 (8단계 속도, 하단 속도 버튼, 중앙 팝업 패널, < / > 단축키) |
| v3.5 | 2026-03-24 | 페후 (이태훈) | 3.4.3 A-B 구간 반복 구현 완료 (A키 3단계, position stream 감시, 진행바 마커, 상태 표시줄) |
| v3.6 | 2026-03-24 | 페후 (이태훈) | 3.4.4 항상 위 구현 완료 (T키 단축키, 상단 핀 버튼, 종료 시 자동 해제, Windows/macOS 전용) |
| v3.7 | 2026-03-24 | 페후 (이태훈) | 3.4.5 키보드 단축키 전체 구현 완료 (Ctrl+O 파일 열기, N/P/R/L/A/>/ 단축키 추가, 도움말 오버레이 섹션별 테이블 + 스크롤, Ctrl+O 포함) |
| v3.8 | 2026-03-24 | 페후 (이태훈) | 3.4.6 Android 터치 제스처 구현 완료 (단일 탭: 컨트롤 토글, 더블탭 좌/우: ±10초, 수직 스와이프 좌: 밝기, 우: 볼륨, 수평 스와이프: 탐색, screen_brightness 패키지 추가) |
| v3.9 | 2026-03-24 | 페후 (이태훈) | 3.4.8 Android 인텐트 파일 열기 구현 완료 (AndroidManifest ACTION_VIEW intent-filter, MainActivity MethodChannel+EventChannel, content:// URI 파일 경로 변환, HomeScreen 인텐트 수신 처리) |
| v4.0 | 2026-03-24 | 페후 (이태훈) | 3.4.9 비디오 프레임 캡처 구현 완료 (player.screenshot()으로 순수 프레임 추출, gal 패키지로 갤러리/Pictures 저장, C 단축키, 상단 바 카메라 버튼, 저장 결과 피드백 오버레이) |
| v4.1 | 2026-03-24 | 페후 (이태훈) | 3.5.3 PIP 구현 완료 (AndroidManifest supportsPictureInPicture, MainActivity PIP MethodChannel+EventChannel, 영상 비율 Rational 전달, PIP 진입 시 컨트롤 숨김/해제 시 복원) |
| v4.2 | 2026-03-24 | 페후 (이태훈) | 3.5.3 PIP 개선 — 홈 버튼 자동 PIP를 영상 재생 중일 때만 동작하도록 수정 (Flutter→Native 재생 상태 공유, setPlaying MethodChannel, dispose 시 false 전달) |
| v4.3 | 2026-03-25 | 페후 (이태훈) | 빌드 출력 파일명 변경 — build_android.bat(BBPlayer.apk 자동 복사), build_windows.bat 스크립트 추가, CMakeLists.txt BINARY_NAME을 BBPlayer로 변경 |
| v4.4 | 2026-03-25 | 페후 (이태훈) | Android intent-filter 개선 — content:// scheme 명시, BROWSABLE 카테고리 추가, http/https scheme 추가 (DS File 등 NAS 스트리밍 앱 연결 지원) |
| v4.5 | 2026-03-25 | 페후 (이태훈) | Kotlin 증분 컴파일 비활성화 — gradle.properties에 kotlin.incremental=false 추가 (C:/D: 드라이브 경로 충돌로 발생하는 Kotlin 데몬 캐시 오류 영구 해결) |
| v4.6 | 2026-03-25 | 페후 (이태훈) | Android 세로 모드 UI 개선 — 하단 컨트롤을 2줄로 분리 (1줄: 재생 버튼 중앙 정렬, 2줄: 시간+반복/셔플/속도+음소거), 볼륨 슬라이더는 세로 모드에서 제거 (제스처로 대체), 가로 모드는 기존 단일 행 유지 |
| v4.7 | 2026-03-25 | 페후 (이태훈) | Android 시스템 UI inset 적용 — 상단/하단/좌우 MediaQuery.padding 반영으로 네비게이션 바·노치·카메라 컷아웃에 의한 버튼 가림 현상 해결 |
| v4.8 | 2026-03-25 | 페후 (이태훈) | 수평 스와이프 실시간 seek 프리뷰 구현 — 드래그 시작 시 플레이어 일시정지, 드래그 중 _player.seek() 실시간 호출로 영상 프리뷰, 드래그 종료 시 재생 재개 (오디오 끊김 방지) |
| v4.9 | 2026-03-25 | 페후 (이태훈) | 방향키 탐색 진행바 즉각 반영 — _seekPreviewPos 변수 추가, 키 입력 시 진행바 즉시 이동 (디바운스 400ms 완료 전에도 시각적 위치 반영) |
| v4.10 | 2026-03-25 | 페후 (이태훈) | 컨트롤 숨김 시 터치 차단 — AnimatedOpacity를 IgnorePointer로 감싸 컨트롤 비표시 상태에서 진행바·버튼 터치 이벤트 완전 차단 (비디오 영역 탭으로 컨트롤 재표시는 정상 동작 유지) |
| v4.11 | 2026-03-25 | 페후 (이태훈) | 재생 에러 오버레이 조건 수정 — stream.error를 duration==0일 때만 표시 (파일 로드 실패 시만 표시, 재생 중 발생하는 mpv 경고성 메시지는 무시), 500ms 지연 후 판단 |
| v4.12 | 2026-03-25 | 페후 (이태훈) | 수평 스와이프 볼륨 복원 버그 수정 — setVolume(0) 호출 시 stream.volume이 _volume을 0으로 덮어쓰는 문제 해결 (_horizDragSavedVolume에 드래그 시작 전 볼륨 저장 후 복원) |
| v4.13 | 2026-03-25 | 페후 (이태훈) | 수평 스와이프 오디오 완전 차단 — setVolume 방식 대신 pause/resume 방식으로 변경 (드래그 중 pause로 오디오 버퍼 재생 방지, 드래그 종료 시 재생 여부에 따라 play 재개) |
| v4.14 | 2026-03-25 | 페후 (이태훈) | Android 플레이어 immersive 모드 적용 — initState에서 SystemChrome.setEnabledSystemUIMode(immersiveSticky) 호출, 플레이어 진입 시 시스템 UI 고정 숨김으로 컨트롤 표시/숨김 전환 시 MediaQuery.padding 변화에 의한 레이아웃 이탈 현상 해결, dispose 시 edgeToEdge로 복원 |
| v4.15 | 2026-03-25 | 페후 (이태훈) | 컨트롤 숨김 시 터치 차단 방식 변경 — IgnorePointer 래핑 방식 제거 (외부 GestureDetector 제스처까지 차단되는 문제 발생), Slider의 onChanged/onChangeStart/onChangeEnd를 _controlsVisible 조건부로 null 처리하는 방식으로 교체 (진행바만 비활성화, 스와이프 제스처 정상 동작 유지) |
| v4.16 | 2026-03-25 | 페후 (이태훈) | Android 뒤로가기 동작 개선 — PopScope 적용으로 시스템 뒤로가기 버튼 인터셉트, _saveAndPop()에서 재생 위치 await 저장 후 SystemNavigator.pop()으로 앱 완전 종료 (홈 화면이 아닌 DS File 등 이전 앱으로 복귀), PC는 기존 Navigator.pop() 유지 |
| v4.17 | 2026-03-25 | 페후 (이태훈) | Android 홈 화면 최근 목록 숨김 — Android는 외부 앱(DS File 등)에서 인텐트로 직접 플레이어 실행하는 사용 패턴으로 최근 목록이 불필요, Platform.isAndroid 조건으로 최근 목록 및 전체 삭제 버튼 미표시 처리 |
| v4.18 | 2026-03-25 | 페후 (이태훈) | Android 시스템 제스처 충돌 방지 엣지 데드존 추가 — 화면 좌/우/하단 32dp 이내에서 시작한 스와이프를 BBPlayer 제스처로 처리하지 않음 (_isEdgeTouch() 헬퍼, _gestureCancelled 플래그, 수직/수평 드래그 핸들러 모두 적용), 시스템 UI 표시용 엣지 스와이프와의 충돌 해결 |
| v4.19 | 2026-03-25 | 페후 (이태훈) | SMI 자막 형식 지원 추가 — 자동 로드 확장자 목록 및 수동 로드 파일 선택 다이얼로그에 .smi 추가 (mpv 기반 media_kit이 SAMI 형식 네이티브 지원), 싱크 오프셋은 SRT와 타임스탬프 구조가 달라 미적용 |
| v4.20 | 2026-03-25 | 페후 (이태훈) | 3.4.7 재생 중 파일 교체 Android 제외 — Android는 외부 앱에서 인텐트로 직접 실행하는 사용 패턴으로 재생 중 파일 교체 불필요, 상단 바 파일 열기 버튼 및 Ctrl+O 단축키를 Windows/macOS 전용으로 제한 |
| v4.21 | 2026-03-25 | 페후 (이태훈) | 3.5.1 진행바 썸네일 미리보기 구현 — Windows/macOS 전용, 별도 _thumbPlayer 인스턴스로 메인 재생 중단 없이 seek+screenshot, 150ms 디바운스, LayoutBuilder로 슬라이더 실제 너비 계산, MouseRegion 호버 추적, 드래그 중 팝업 자동 숨김 |
| v4.22 | 2026-03-25 | 페후 (이태훈) | 3.5.4 드래그 앤 드롭 구현 — desktop_drop 패키지 추가, DropTarget으로 전체 화면 래핑(Android 제외), 드롭 위치(localPosition.dx)로 교체/추가 분기, 플레이리스트 열림 여부에 따라 좌측(파일 교체)/우측(목록 추가) 오버레이 UI, 다중 파일 드롭 지원 |
이태훈이(가) 약 한달 전에 변경 · 1 revisions