프로젝트

일반

사용자정보

개발계획서 » 이력 » 버전 1

이태훈, 2026/03/25 01:33

1 1 이태훈
h1. 개발계획서
2
3
h1. BBPlayer 개발계획서
4
5
|_.항목|_.내용|
6
|프로젝트명|BBPlayer|
7
|프로그램명|BBPlayer|
8
|문서 버전|v4.22|
9
|작성일|2026년 03월 25일|
10
|작성자|페후 (이태훈)|
11
|상태|진행 중 (In Progress)|
12
13
---
14
15
h2. 1. 개발 목표
16
17
기존 동영상 플레이어의 자막 오류 및 소리 문제를 개선하고, Windows 데스크탑과 Android 모바일 환경을 모두 지원하는 크로스플랫폼 동영상 플레이어 *BBPlayer*를 개발한다.
18
19
---
20
21
h2. 2. 개발 환경
22
23
|_.구분|_.내용|
24
|개발 언어|Dart|
25
|프레임워크|Flutter|
26
|타겟 플랫폼|Windows 10 이상 (64bit), Android 8.0 (API 26) 이상, macOS|
27
|미디어 엔진|media_kit (FFmpeg 기반)|
28
|로컬 DB|sqflite (SQLite)|
29
|윈도우 관리|window_manager|
30
|앱 아이콘|flutter_launcher_icons (BBPlayerIcon.png 기반 자동 생성)|
31
|IDE|Android Studio / VS Code|
32
33
---
34
35
h2. 3. 기능별 개발계획
36
37
h3. Phase 1 — 핵심 재생 기능
38
39
bq. 목표: 앱 실행 후 영상 파일을 열고 기본 재생이 가능한 상태
40
41
h4. 3.1.1 파일 열기 (FR 연관: FR-17, Ctrl+O) ✅ 완료
42
43
|_.항목|_.내용|
44
|기능|file_picker를 통해 파일 탐색기에서 영상 파일 선택 및 로드|
45
|지원 포맷|MP4, MKV, AVI, MOV, FLV, WMV|
46
|플랫폼|Windows / Android / macOS|
47
|구현 포인트|@file_picker@ 패키지 연동, media_kit Player에 파일 경로 전달|
48
|완료 조건|파일 선택 후 2초 이내 재생 시작|
49
|완료일|2026-03-24|
50
|비고|Windows 정상 동작 확인|
51
52
h4. 3.1.2 재생 / 일시정지 (FR-01) ✅ 완료
53
54
|_.항목|_.내용|
55
|기능|컨트롤 바 버튼 및 단축키(Space)로 재생/일시정지 토글|
56
|플랫폼|Windows / Android / macOS|
57
|구현 포인트|@media_kit@ Player.playOrPause() 연동, 중앙 아이콘 애니메이션 피드백|
58
|완료 조건|버튼 및 Space 키 입력 시 즉각 토글 동작|
59
|완료일|2026-03-24|
60
|비고|화면 탭/클릭 토글, 재생 중 3초 후 컨트롤 자동 숨김, 마우스 이동 시 컨트롤 재표시 추가, 컨트롤 수동 숨김 토글 추가 (Windows/macOS: H키, Android: 상단 바 숨김 버튼)|
61
62
h4. 3.1.3 재생 진행바 (FR-03) ✅ 완료
63
64
|_.항목|_.내용|
65
|기능|전체 길이 대비 현재 위치 표시, 드래그로 탐색|
66
|플랫폼|Windows / Android / macOS|
67
|구현 포인트|@VideoController@ position stream 구독, Slider 위젯 연동, seek() 호출|
68
|완료 조건|드래그 탐색 후 0.5초 이내 화면 반영|
69
|완료일|2026-03-24|
70
|비고|드래그 중 위치 떨림 방지 (_isDragging 상태 분리), 드래그 중 파란색 시간 툴팁 표시, 드래그 중 자동 숨김 타이머 정지, 방향키 탐색 시 일시정지→seek→재생 동작 추가, 연속 입력 시 누적 이동량 표시 (→ 10초 / Shift+→ 30초), 방향키 입력 시 진행바 즉각 반영 (_seekPreviewPos로 디바운스 전 시각적 위치 업데이트)|
71
72
h4. 3.1.4 볼륨 조절 / 음소거 (FR-14, FR-15) ✅ 완료
73
74
|_.항목|_.내용|
75
|기능|0~100% 슬라이더 조절, 음소거 토글 및 이전 볼륨 복원|
76
|플랫폼|Windows / Android / macOS|
77
|구현 포인트|@Player.setVolume()@, 음소거 전 볼륨 상태 로컬 변수 보존|
78
|단축키|↑/↓ (5% 단위), M (음소거)|
79
|완료 조건|슬라이더 및 단축키 모두 정상 동작|
80
|완료일|2026-03-24|
81
|비고|컨트롤 바 내 볼륨 슬라이더 + 음소거 버튼 추가, 볼륨 변경 시 우측 상단 오버레이 표시 (2초 후 자동 숨김), 음소거 해제 시 이전 볼륨 복원|
82
83
h4. 3.1.5 전체화면 토글 (FR-05) ✅ 완료
84
85
|_.항목|_.내용|
86
|기능|전체화면 진입 및 해제|
87
|플랫폼|Windows / Android / macOS|
88
|구현 포인트|@window_manager@ (Windows/macOS), @SystemChrome.setEnabledSystemUIMode@ (Android)|
89
|단축키|F / F11 (토글), Esc (전체화면 해제 → 이미 해제 상태면 뒤로가기)|
90
|완료 조건|전체화면 진입/해제 시 정상 동작|
91
|완료일|2026-03-24|
92
|비고|상단 바 전체화면 버튼 추가, 플레이어 종료 시 전체화면 자동 해제|
93
94
---
95
96
h3. Phase 2 — 자막 & 오디오
97
98
bq. 목표: 외부 자막 파일 적용 및 다중 오디오 트랙 선택
99
100
h4. 3.2.1 자막 파일 불러오기 (FR-09) ✅ 완료
101
102
|_.항목|_.내용|
103
|기능|SRT / ASS 형식의 외부 자막 파일 자동 로드 + 수동 로드|
104
|플랫폼|Windows / Android / macOS|
105
|구현 포인트|@file_picker@로 자막 파일 경로 선택, @subtitle_view@ 패키지 파싱|
106
|완료 조건|자막 선택 즉시 영상 위에 정상 표시|
107
108
*자동 로드*
109
* 재생 시작 시 영상 파일과 동일 폴더 내 동일 이름의 자막 파일(@.srt@, @.ass@, @.ssa@) 자동 탐색
110
* 자막 파일 발견 시 알림 없이 즉시 적용
111
* 우선순위: @.srt@ → @.ass@ → @.ssa@
112
113
*수동 로드*
114
* 컨트롤 바 자막 버튼 또는 단축키(@S@ 길게 누르기)로 파일 탐색기 열기
115
* 수동 로드 시 자동 로드된 자막을 덮어씀
116
117
|_.완료일|_.비고|
118
|2026-03-24|media_kit SubtitleTrack.uri() 활용, 자막 버튼 파란색(활성)/회색(비활성) 표시, 하단에 자막 파일명 표시, S키 ON/OFF 토글 (자막 없으면 파일 탐색기 오픈)|
119
120
h4. 3.2.2 자막 싱크 조절 (FR-10) ✅ 완료
121
122
|_.항목|_.내용|
123
|기능|자막 표시 시간을 ±0.1초 단위로 수동 조정|
124
|플랫폼|Windows / Android / macOS|
125
|구현 포인트|SubtitleService.applySrtOffset()으로 SRT 타임스탬프 재파싱 → 임시 파일 저장 → media_kit 재로드|
126
|단축키|@[@ (-0.1s) / @]@ (+0.1s)|
127
|완료 조건|조절 즉시 자막 타이밍에 반영|
128
|완료일|2026-03-24|
129
|비고|SRT 전용 오프셋 처리, 좌측 상단 싱크 오버레이 3초 표시, 하단 자막 바에 ±0.1s 버튼 및 현재 오프셋 표시, 새 자막 로드 시 오프셋 0으로 초기화|
130
131
h4. 3.2.3 자막 ON/OFF (FR-11) ✅ 완료
132
133
|_.항목|_.내용|
134
|기능|자막 표시 여부 즉시 토글|
135
|플랫폼|Windows / Android / macOS|
136
|단축키|S|
137
|완료 조건|토글 즉시 자막 표시/숨김 전환|
138
|완료일|2026-03-24|
139
|비고|3.2.1 구현 시 함께 완료. SubtitleTrack.no()로 OFF, SubtitleTrack.uri()로 ON, 자막 없으면 S키가 파일 탐색기 오픈으로 동작|
140
141
h4. 3.2.4 자막 스타일 커스터마이징 (FR-12) ✅ 완료
142
143
|_.항목|_.내용|
144
|기능|자막 글자 크기, 색상, 배경색 사용자 설정|
145
|플랫폼|Windows / Android / macOS|
146
|구현 포인트|SubtitleViewConfiguration으로 TextStyle 적용, 설정 패널 오버레이, sqflite settings 테이블에 저장/복원|
147
|완료 조건|설정 변경 즉시 자막에 반영, 앱 재실행 후에도 유지|
148
|완료일|2026-03-24|
149
|비고|글자 크기 4단계(소22/중32/대44/특대56), 글자 색상 4종(흰색/노란색/하늘색/연두색), 배경 3종(없음/반투명/불투명). 상단 바 자막 스타일 버튼(Aa)으로 패널 토글. DatabaseService에 getSetting/setSetting 추가|
150
151
h4. 3.2.5 오디오 트랙 선택 (FR-16) ✅ 완료
152
153
|_.항목|_.내용|
154
|기능|다중 오디오 트랙(MKV 등)에서 원하는 트랙 선택|
155
|플랫폼|Windows / Android / macOS|
156
|구현 포인트|@_player.stream.tracks@ / @_player.stream.track@ 구독, @_player.setAudioTrack()@ 호출|
157
|완료 조건|트랙 목록 표시 및 선택 후 즉시 오디오 전환|
158
|완료일|2026-03-24|
159
|비고|트랙 2개 이상일 때만 하단 바 오디오 버튼 표시. 트랙명/언어 코드 표시, 현재 선택 트랙 강조. 우측 하단 패널 오버레이로 목록 표시|
160
161
---
162
163
h3. Phase 3 — 플레이리스트
164
165
bq. 목표: 여러 파일을 연속 재생하고 재생 이력을 관리
166
167
h4. 3.3.1 플레이리스트 파일 추가 (FR-17) ✅ 완료
168
169
|_.항목|_.내용|
170
|기능|파일 탐색기로 개별 파일 또는 폴더 단위 영상 추가|
171
|플랫폼|Windows / Android / macOS|
172
|구현 포인트|@file_picker@ 다중 선택 / getDirectoryPath + dart:io Directory.list() 스캔|
173
|완료 조건|선택한 파일/폴더 내 영상이 플레이리스트에 정상 추가|
174
|완료일|2026-03-24|
175
|비고|PlayerScreen이 playlist + initialIndex를 받는 구조로 변경. 홈/플레이어 모두에서 파일/폴더 추가 가능. 우측 슬라이드 패널로 목록 표시, L키/상단 버튼으로 토글. 항목 탭으로 즉시 전환, X버튼으로 삭제. 폴더 추가 시 알파벳순 정렬|
176
177
h4. 3.3.2 이전 / 다음 영상 이동 (FR-19) ✅ 완료
178
179
|_.항목|_.내용|
180
|기능|플레이리스트 내 이전/다음 영상으로 이동|
181
|플랫폼|Windows / Android / macOS|
182
|단축키|N (다음), P (이전)|
183
|완료 조건|버튼 및 단축키로 정상 이동|
184
|완료일|2026-03-24|
185
|비고|영상 종료 시 자동으로 다음 영상 재생 (마지막 항목이면 정지 유지). P키는 3초 이내면 처음으로 되감기, 이후면 이전 영상 이동. 플레이리스트 2개 이상일 때만 이전/다음 버튼 표시. 마지막 항목에서 N키 수동 조작 시 처음으로 순환|
186
187
h4. 3.3.3 반복 재생 모드 (FR-20) ✅ 완료
188
189
|_.항목|_.내용|
190
|기능|전체 반복 / 한 곡 반복 / 셔플 모드 선택|
191
|플랫폼|Windows / Android / macOS|
192
|구현 포인트|RepeatMode enum (none/all/one), _isShuffle bool, _playNext 내 분기 처리|
193
|완료 조건|모드 전환 후 재생 순서에 즉시 반영|
194
|완료일|2026-03-24|
195
|비고|R키로 반복 모드 순환 (없음→전체→한 곡). 셔플은 버튼 전용. 한 곡 반복 시 seek(0)+play로 재시작. 셔플+이전 이동도 랜덤 인덱스 적용. 반복/셔플 활성화 시 버튼 파란색 강조|
196
197
h4. 3.3.4 이어보기 (FR-07) ✅ 완료
198
199
|_.항목|_.내용|
200
|기능|앱 종료 후 재실행 시 마지막 재생 위치부터 자동 이어 재생|
201
|플랫폼|Windows / Android / macOS|
202
|구현 포인트|sqflite play_history 테이블에 저장/복원, WidgetsBindingObserver로 백그라운드 전환 감지, 5초 주기 자동 저장|
203
|완료 조건|재실행 후 이전 위치에서 자동 재개|
204
|완료일|2026-03-24|
205
|비고|저장 시점 3단계: ① 재생 중 5초 주기 자동 저장 ② 백그라운드/비활성 전환 시 즉시 저장 (AppLifecycleState) ③ dispose(화면 이탈) 시 저장. 복원은 _initPlayback()에서 getLastPosition() 후 seek()|
206
207
h4. 3.3.5 최근 재생 목록 (FR-21) ✅ 완료
208
209
|_.항목|_.내용|
210
|기능|최근 재생 파일 히스토리 저장 및 빠른 열기|
211
|플랫폼|Windows / Android / macOS|
212
|구현 포인트|sqflite play_history 테이블, 홈 화면 ListView, Dismissible 스와이프 삭제, 전체 삭제|
213
|완료 조건|목록에서 항목 선택 시 해당 파일 즉시 재생|
214
|완료일|2026-03-24|
215
|비고|홈 화면 목록에 항목 수 표시. 좌로 스와이프 → 개별 삭제. 앱 바 휴지통 버튼 → 전체 삭제 (확인 다이얼로그). DatabaseService에 deleteHistory / clearAllHistory 메서드 추가|
216
217
---
218
219
h3. Phase 4 — 편의 기능
220
221
bq. 목표: 생산성과 사용 편의성을 높이는 고급 조작 기능
222
223
h4. 3.4.1 앞/뒤로 이동 (FR-02) ✅ 완료
224
225
|_.항목|_.내용|
226
|기능|단축키로 현재 위치에서 이동|
227
|플랫폼|Windows / Android / macOS|
228
|단축키|→/← (±10초), Shift+→/← (±30초)|
229
|완료 조건|정확한 시간 이동, 연속 입력 시 누적 반영|
230
|완료일|2026-03-24|
231
|비고|3.1.3 구현 시 함께 완료. _arrowSeek()로 누적 후 400ms 디바운스, 일시정지→seek→재생 동작. 중앙 피드백 아이콘 + 누적량 표시|
232
233
h4. 3.4.2 재생 속도 조절 (FR-04) ✅ 완료
234
235
|_.항목|_.내용|
236
|기능|0.25x ~ 2.0x 범위 (0.25x 단위) 속도 선택|
237
|플랫폼|Windows / Android / macOS|
238
|구현 포인트|@Player.setRate()@ 호출, 하단 바 속도 버튼 + 중앙 팝업 패널|
239
|완료 조건|속도 변경 즉시 재생에 반영|
240
|완료일|2026-03-24|
241
|비고|0.25/0.5/0.75/1.0/1.25/1.5/1.75/2.0x 8단계. 하단 바 속도 버튼(1.0x 표시, 1.0x 아닐 때 파란색 강조). < / > 키로 단계 조절. 선택 즉시 패널 닫힘|
242
243
h4. 3.4.3 A-B 구간 반복 (FR-08) ✅ 완료
244
245
|_.항목|_.내용|
246
|기능|A(시작점)와 B(종료점) 지정 후 해당 구간 무한 반복|
247
|플랫폼|Windows / Android / macOS|
248
|단축키|A (1회: A 설정, 2회: B 설정+반복 시작, 3회: 해제)|
249
|구현 포인트|position stream에서 B 도달 시 A로 seek(), 진행바에 A/B 마커 표시|
250
|완료 조건|A-B 구간 정확히 반복, 해제 시 정상 종료|
251
|완료일|2026-03-24|
252
|비고|A보다 앞에서 B 설정 시 A 재설정. 진행바 위 녹색(A)/빨간색(B) 수직 마커. 하단 A↔B 상태 표시줄 + X 버튼 해제. 파일 교체 시 자동 초기화|
253
254
h4. 3.4.4 항상 위 (Always on Top) (FR-06) ✅ 완료
255
256
|_.항목|_.내용|
257
|기능|플레이어 창을 항상 최상위로 표시|
258
|플랫폼|Windows / macOS (window_manager 지원 데스크탑 전용)|
259
|구현 포인트|@windowManager.setAlwaysOnTop()@ 호출, T키 단축키, 상단 핀 버튼|
260
|완료 조건|토글 시 창 최상위/일반 전환 정상 동작|
261
|완료일|2026-03-24|
262
|비고|T키 단축키, 상단 바 핀 아이콘 버튼 (활성 시 파란색). Android에서는 버튼 미표시. 플레이어 종료 시 자동 해제|
263
264
h4. 3.4.5 키보드 단축키 전체 구현 + 도움말 오버레이 (FR 연관: 2.6절) ✅ 완료
265
266
|_.항목|_.내용|
267
|기능|Space, 방향키 (±10초 / Shift ±30초), F/F11, Esc, M, S, [, ], H, ? 단축키 전체 지원 + 도움말 오버레이|
268
|플랫폼|Windows / macOS / Android (도움말 버튼은 전 플랫폼 공통)|
269
|구현 포인트|@HardwareKeyboard@ API 활용, @?@ 키 또는 상단 바 버튼으로 오버레이 토글|
270
|도움말 내용|Space(재생/정지), →/←(±10초), Shift+→/←(±30초), ↑/↓(볼륨), M(음소거), S(자막), [/](자막 싱크), F/F11(전체화면), H(컨트롤 숨김), ?(도움말)|
271
|완료 조건|모든 단축키 정상 동작, 도움말 오버레이 표시/숨김 정상 동작|
272
|완료일|2026-03-24|
273
274
h4. 3.4.7 재생 중 파일 교체 ✅ 완료 (Windows/macOS 전용)
275
276
|_.항목|_.내용|
277
|기능|재생 중 현재 파일을 다른 파일로 즉시 교체|
278
|플랫폼|Windows / macOS (Android 제외 — 외부 앱 인텐트 실행 방식으로 불필요)|
279
|방식 1|플레이어 상단 바 파일 열기 버튼 → file_picker로 새 파일 선택 → 즉시 교체 재생|
280
|방식 2|드래그 앤 드롭으로 플레이어 화면에 파일 드롭 → 즉시 교체 재생 (3.5.4와 연계)|
281
|구현 포인트|교체 시 자막 오프셋 초기화, 재생 위치 초기화, 이전 파일 히스토리 저장 후 신규 파일 재생|
282
|완료 조건|버튼 및 드래그 앤 드롭으로 파일 교체 후 즉시 재생|
283
|완료일|2026-03-25|
284
|비고|파일 경로는 _currentFilePath로 추적. Android는 DS File 등 외부 앱에서 인텐트로 직접 실행하는 패턴으로 재생 중 파일 교체 기능 제외|
285
286
h4. 3.4.6 터치 제스처 제어 (Android 전용, FR 연관: 2.5절) ✅ 완료
287
288
|_.항목|_.내용|
289
|기능|스와이프로 탐색/밝기/볼륨 조절, 탭으로 컨트롤 토글, 더블탭으로 ±10초|
290
|플랫폼|Android 전용|
291
|구현 포인트|@GestureDetector@, @screen_brightness@ 패키지 활용, 제스처 영역 분할|
292
|제스처 상세|단일 탭: 컨트롤 표시/숨김 / 더블탭 왼쪽: -10초 / 더블탭 오른쪽: +10초 / 수직 스와이프 왼쪽 절반: 밝기 / 수직 스와이프 오른쪽 절반: 볼륨 / 수평 스와이프: 탐색 (스크린 가로폭 100% = 180초)|
293
|오버레이|제스처 동작 중 화면 중앙에 아이콘 + 수치 표시, 2초 후 자동 소멸|
294
|완료 조건|모든 제스처 방향 및 영역별 동작 정상|
295
|완료일|2026-03-24|
296
297
h4. 3.4.9 비디오 프레임 캡처 ✅ 완료
298
299
|_.항목|_.내용|
300
|기능|현재 재생 중인 비디오 프레임을 UI 없이 순수 영상만 캡처하여 저장|
301
|플랫폼|Windows / Android / macOS|
302
|구현 포인트|@player.screenshot()@ (media_kit 내장, libmpv 디코더에서 직접 추출) → @gal@ 패키지로 저장|
303
|저장 위치|Android: 갤러리(BBPlayer 앨범) / Windows: Pictures\BBPlayer\ / macOS: 사진 앱|
304
|트리거|상단 바 카메라 버튼 또는 @C@ 단축키|
305
|피드백|저장 성공/실패 오버레이 2초 표시|
306
|완료 조건|버튼/단축키 → 순수 영상 프레임 저장 확인|
307
|완료일|2026-03-24|
308
|비고|Flutter UI(버튼, 자막 오버레이 등) 미포함. gal 패키지 추가, Android WRITE_EXTERNAL_STORAGE 권한 추가(maxSdkVersion=29)|
309
310
h4. 3.4.8 외부 앱에서 동영상 파일 열기 (Android 인텐트) ✅ 완료
311
312
|_.항목|_.내용|
313
|기능|파일 매니저 등 외부 앱에서 동영상 파일을 선택 시 BBPlayer가 앱 선택 목록에 표시되고, 선택 시 즉시 재생|
314
|플랫폼|Android 전용|
315
|구현 포인트|AndroidManifest.xml에 @ACTION_VIEW@ + @video/*@ intent-filter 추가, MainActivity에 MethodChannel(초기 실행) + EventChannel(실행 중 수신) 구현|
316
|URI 처리|content:// URI는 MediaStore를 통해 실제 파일 경로로 변환 시도, 실패 시 URI 그대로 media_kit에 전달|
317
|완료 조건|파일 매니저에서 동영상 탭 → 앱 선택 목록에 BBPlayer 표시 → 선택 시 즉시 재생|
318
|완료일|2026-03-24|
319
|비고|intent-filter에 content:// scheme 명시 및 BROWSABLE 카테고리 추가, http/https scheme 추가로 DS File 등 NAS 스트리밍 앱에서도 BBPlayer 선택 가능|
320
321
---
322
323
h3. Phase 5 — 고급 기능
324
325
bq. 목표: 사용자 경험을 극대화하는 부가 기능
326
327
h4. 3.5.1 진행바 썸네일 미리보기 (FR-22) ✅ 완료
328
329
|_.항목|_.내용|
330
|기능|진행바에 마우스 오버 시 해당 위치의 썸네일 팝업 표시|
331
|플랫폼|Windows / macOS (마우스 입력 가능 데스크탑 전용)|
332
|구현 포인트|별도 @Player@ 인스턴스(@_thumbPlayer@)로 메인 재생 중단 없이 프레임 seek → @screenshot()@ → @Image.memory()@ 팝업 표시, 150ms 디바운스, 드래그 중 숨김|
333
|완료 조건|마우스 위치에 따라 정확한 썸네일 표시|
334
335
h4. 3.5.2 자막 자동 검색 (FR-13) ❌ 취소
336
337
|_.항목|_.내용|
338
|기능|재생 중 파일명 기준으로 외부 자막 사이트 검색 및 다운로드 제안|
339
|플랫폼|Windows / Android / macOS|
340
|구현 포인트|자막 API 연동 (OpenSubtitles 등), HTTP 요청, 다운로드 후 자동 적용|
341
|완료 조건|검색 결과 목록 표시 및 선택한 자막 자동 적용|
342
343
bq. ❌ *취소 사유:* 사용 빈도 낮고 외부 API 의존성 및 유지보수 부담 대비 실용성 부족. 필요 시 자막 파일을 영상과 동일 폴더에 배치하는 기존 자동 로드 방식으로 대체 가능.
344
345
h4. 3.5.3 PIP (Picture in Picture) (FR-23) ✅ 완료
346
347
|_.항목|_.내용|
348
|기능|다른 앱 사용 중 영상을 작은 플로팅 창으로 재생|
349
|플랫폼|Android 전용 (API 26 이상)|
350
|구현 포인트|AndroidManifest @supportsPictureInPicture="true"@, MainActivity PIP MethodChannel + PIP 상태 EventChannel, Flutter에서 영상 비율로 @PictureInPictureParams@ 전달|
351
|PIP 진입|상단 바 PIP 버튼 탭 → @enterPictureInPictureMode()@ 호출|
352
|PIP 중 동작|컨트롤 전체 숨김, 영상만 표시, 재생 유지|
353
|PIP 해제|창 확대 시 자동으로 컨트롤 복원|
354
|완료 조건|PIP 진입/해제 및 영상 재생 정상 동작|
355
|완료일|2026-03-24|
356
357
h4. 3.5.4 드래그 앤 드롭 (FR-18) ✅ 완료
358
359
|_.항목|_.내용|
360
|기능|파일 탐색기에서 드래그하여 파일 추가 또는 교체|
361
|플랫폼|Windows / macOS (desktop_drop 데스크탑 전용)|
362
|동작 구분|플레이어 화면에 드롭 → 현재 파일 즉시 교체 (3.4.7 연계) / 플레이리스트에 드롭 → 목록에 추가|
363
|구현 포인트|@desktop_drop@ 패키지, @DropTarget@으로 전체 화면 래핑, @detail.localPosition.dx@로 드롭 위치 판별, 드래그 중 영역별 오버레이 UI 표시|
364
|완료 조건|드롭 위치에 따른 교체/추가 동작 정상 처리|
365
|완료일|2026-03-25|
366
367
---
368
369
h2. 4. 데이터 설계
370
371
h3. 4.1 로컬 DB 테이블 (sqflite)
372
373
h4. play_history (최근 재생 / 이어보기)
374
375
|_.컬럼|_.타입|_.설명|
376
|id|INTEGER PK|자동 증가|
377
|file_path|TEXT|영상 파일 경로|
378
|last_position|INTEGER|마지막 재생 위치 (밀리초)|
379
|played_at|TEXT|마지막 재생 일시 (ISO8601)|
380
381
h4. settings (앱 설정)
382
383
|_.컬럼|_.타입|_.설명|
384
|key|TEXT PK|설정 키|
385
|value|TEXT|설정 값|
386
387
bq. 설정 항목 예시: subtitle_font_size, subtitle_color, subtitle_bg_color, theme_mode, volume
388
389
---
390
391
h2. 5. 개발 일정
392
393
|_.Phase|_.기능|_.예상 기간|_.상태|
394
|Phase 1|핵심 재생 기능 (파일 열기, 재생/정지, 진행바, 볼륨, 전체화면)|2주|✅ 완료|
395
|Phase 2|자막 & 오디오 (자막 로드, 싱크, 스타일, 오디오 트랙)|2주|✅ 완료|
396
|Phase 3|플레이리스트 (파일 추가, 이전/다음, 반복, 이어보기, 최근 목록)|2주|✅ 완료|
397
|Phase 4|편의 기능 (A-B 반복, 속도 조절, 단축키, 제스처, Always on Top)|2주|✅ 완료|
398
|Phase 5|고급 기능 (썸네일 미리보기, 자막 자동 검색, PIP, 드래그 앤 드롭)|3주|✅ 완료|
399
|통합 테스트|Windows / Android / macOS 전 기능 검증 및 버그 수정|1주|대기|
400
|*합계*||*약 12주*||
401
402
---
403
404
h2. 6. 리스크 및 대응 방안
405
406
|_.리스크|_.대응 방안|
407
|media_kit Windows/Android 코덱 호환 이슈|FFmpeg 빌드 플래그 확인, 포맷별 테스트 케이스 작성|
408
|자막 싱크 정확도 저하|subtitle_view 파싱 로직 직접 오프셋 처리, 단위 테스트 작성|
409
|Android PIP API 버전 파편화|API 26 이상 조건부 활성화, 구버전 graceful fallback 처리|
410
|썸네일 추출 성능 저하|백그라운드 Isolate에서 추출, LRU 캐시 적용|
411
|자막 자동 검색 외부 API 변경|API 추상화 레이어 설계, 복수 자막 소스 지원|
412
413
---
414
415
h2. 7. 변경 이력
416
417
|_.버전|_.일자|_.작성자|_.변경 내용|
418
|v1.0|2026-03-24|페후 (이태훈)|최초 작성|
419
|v1.1|2026-03-24|페후 (이태훈)|타겟 플랫폼 macOS 추가, 3.1.1 파일 열기 완료 처리|
420
|v1.2|2026-03-24|페후 (이태훈)|3.1.2 재생/일시정지 완료 처리|
421
|v1.3|2026-03-24|페후 (이태훈)|3.1.3 재생 진행바 완료 처리|
422
|v1.4|2026-03-24|페후 (이태훈)|방향키 이동 10초로 변경, Shift+방향키 30초 추가, 탐색 시 일시정지→seek→재생 동작 추가, 연속 입력 누적 표시 추가|
423
|v1.5|2026-03-24|페후 (이태훈)|3.1.4 볼륨 조절/음소거 완료 처리|
424
|v1.6|2026-03-24|페후 (이태훈)|3.1.5 전체화면 토글 완료 처리, window_manager 패키지 추가, Phase 1 전체 완료|
425
|v1.7|2026-03-24|페후 (이태훈)|앱 타이틀 BBPlayer로 통일 (macOS AppInfo.xcconfig 수정), flutter_launcher_icons로 전 플랫폼 아이콘 자동 생성 적용|
426
|v1.8|2026-03-24|페후 (이태훈)|3.2.1 자막 불러오기에 자동 로드 기능 추가 (동일 이름 자막 자동 탐색 및 적용, 수동 로드와 병행)|
427
|v1.9|2026-03-24|페후 (이태훈)|3.2.1 자막 불러오기 구현 완료 (자동/수동 로드, 자막 버튼, 파일명 표시, S키 토글)|
428
|v2.0|2026-03-24|페후 (이태훈)|3.2.2 자막 싱크 조절 구현 완료 (SubtitleService SRT 파싱, [ / ] 단축키, ±0.1s 버튼, 싱크 오버레이)|
429
|v2.1|2026-03-24|페후 (이태훈)|3.2.3 자막 ON/OFF 완료 처리 (3.2.1 구현 시 이미 포함됨 확인)|
430
|v2.2|2026-03-24|페후 (이태훈)|3.4.5에 단축키 도움말 오버레이 추가 (? 키 / 상단 키보드 버튼, 전체 단축키 테이블 표시, 외부 탭으로 닫기)|
431
|v2.3|2026-03-24|페후 (이태훈)|3.4.7 재생 중 파일 교체 신규 항목 추가 (버튼 방식 + 드래그 앤 드롭 방식), 3.5.4 드래그 앤 드롭 드롭 위치별 동작 분기 내용 추가|
432
|v2.4|2026-03-24|페후 (이태훈)|3.4.7 파일 열기 버튼 방식 구현 완료 (플레이어 상단 바 폴더 버튼, 히스토리 저장 후 새 파일 교체, 자막/오프셋 초기화)|
433
|v2.5|2026-03-24|페후 (이태훈)|3.4.7 버그 수정 — 파일 교체 시 중단 시점 저장 경로 오류 수정 (widget.filePath → _currentFilePath, 2회 이상 교체 시 이전 파일 위치가 원본 경로로 잘못 저장되던 문제 해결)|
434
|v2.6|2026-03-24|페후 (이태훈)|3.2.4 자막 스타일 커스터마이징 구현 완료 (크기 4단계, 색상 4종, 배경 3종, 설정 DB 저장/복원, DatabaseService getSetting/setSetting 추가)|
435
|v2.7|2026-03-24|페후 (이태훈)|3.2.5 오디오 트랙 선택 구현 완료 (tracks/track 스트림 구독, 트랙 2개 이상 시 버튼 표시, 우측 하단 패널, 선택 즉시 전환)|
436
|v2.8|2026-03-24|페후 (이태훈)|3.3.1 플레이리스트 파일 추가 구현 완료 (PlayerScreen playlist 구조 변경, 홈 화면 다중 파일/폴더 선택, 플레이어 우측 패널, L키 단축키)|
437
|v2.9|2026-03-24|페후 (이태훈)|3.3.2 이전/다음 영상 이동 구현 완료 (N/P 단축키, 이전/다음 버튼, 영상 종료 자동 다음 재생, P키 3초 룰)|
438
|v3.0|2026-03-24|페후 (이태훈)|3.3.3 반복 재생 모드 구현 완료 (RepeatMode enum, 셔플, R키 단축키, 반복/셔플 버튼)|
439
|v3.1|2026-03-24|페후 (이태훈)|3.3.4 이어보기 강화 — 5초 자동 저장 타이머, AppLifecycleState 백그라운드 저장, WidgetsBindingObserver 추가|
440
|v3.2|2026-03-24|페후 (이태훈)|3.3.5 최근 재생 목록 완료 — 스와이프 개별 삭제, 전체 삭제 확인 다이얼로그, 항목 수 표시, DatabaseService deleteHistory/clearAllHistory 추가|
441
|v3.3|2026-03-24|페후 (이태훈)|3.4.1 완료 처리 (3.1.3 구현 시 이미 포함됨 확인)|
442
|v3.4|2026-03-24|페후 (이태훈)|3.4.2 재생 속도 조절 구현 완료 (8단계 속도, 하단 속도 버튼, 중앙 팝업 패널, < / > 단축키)|
443
|v3.5|2026-03-24|페후 (이태훈)|3.4.3 A-B 구간 반복 구현 완료 (A키 3단계, position stream 감시, 진행바 마커, 상태 표시줄)|
444
|v3.6|2026-03-24|페후 (이태훈)|3.4.4 항상 위 구현 완료 (T키 단축키, 상단 핀 버튼, 종료 시 자동 해제, Windows/macOS 전용)|
445
|v3.7|2026-03-24|페후 (이태훈)|3.4.5 키보드 단축키 전체 구현 완료 (Ctrl+O 파일 열기, N/P/R/L/A/</>/ 단축키 추가, 도움말 오버레이 섹션별 테이블 + 스크롤, Ctrl+O 포함)|
446
|v3.8|2026-03-24|페후 (이태훈)|3.4.6 Android 터치 제스처 구현 완료 (단일 탭: 컨트롤 토글, 더블탭 좌/우: ±10초, 수직 스와이프 좌: 밝기, 우: 볼륨, 수평 스와이프: 탐색, screen_brightness 패키지 추가)|
447
|v3.9|2026-03-24|페후 (이태훈)|3.4.8 Android 인텐트 파일 열기 구현 완료 (AndroidManifest ACTION_VIEW intent-filter, MainActivity MethodChannel+EventChannel, content:// URI 파일 경로 변환, HomeScreen 인텐트 수신 처리)|
448
|v4.0|2026-03-24|페후 (이태훈)|3.4.9 비디오 프레임 캡처 구현 완료 (player.screenshot()으로 순수 프레임 추출, gal 패키지로 갤러리/Pictures 저장, C 단축키, 상단 바 카메라 버튼, 저장 결과 피드백 오버레이)|
449
|v4.1|2026-03-24|페후 (이태훈)|3.5.3 PIP 구현 완료 (AndroidManifest supportsPictureInPicture, MainActivity PIP MethodChannel+EventChannel, 영상 비율 Rational 전달, PIP 진입 시 컨트롤 숨김/해제 시 복원)|
450
|v4.2|2026-03-24|페후 (이태훈)|3.5.3 PIP 개선 — 홈 버튼 자동 PIP를 영상 재생 중일 때만 동작하도록 수정 (Flutter→Native 재생 상태 공유, setPlaying MethodChannel, dispose 시 false 전달)|
451
|v4.3|2026-03-25|페후 (이태훈)|빌드 출력 파일명 변경 — build_android.bat(BBPlayer.apk 자동 복사), build_windows.bat 스크립트 추가, CMakeLists.txt BINARY_NAME을 BBPlayer로 변경|
452
|v4.4|2026-03-25|페후 (이태훈)|Android intent-filter 개선 — content:// scheme 명시, BROWSABLE 카테고리 추가, http/https scheme 추가 (DS File 등 NAS 스트리밍 앱 연결 지원)|
453
|v4.5|2026-03-25|페후 (이태훈)|Kotlin 증분 컴파일 비활성화 — gradle.properties에 kotlin.incremental=false 추가 (C:/D: 드라이브 경로 충돌로 발생하는 Kotlin 데몬 캐시 오류 영구 해결)|
454
|v4.6|2026-03-25|페후 (이태훈)|Android 세로 모드 UI 개선 — 하단 컨트롤을 2줄로 분리 (1줄: 재생 버튼 중앙 정렬, 2줄: 시간+반복/셔플/속도+음소거), 볼륨 슬라이더는 세로 모드에서 제거 (제스처로 대체), 가로 모드는 기존 단일 행 유지|
455
|v4.7|2026-03-25|페후 (이태훈)|Android 시스템 UI inset 적용 — 상단/하단/좌우 MediaQuery.padding 반영으로 네비게이션 바·노치·카메라 컷아웃에 의한 버튼 가림 현상 해결|
456
|v4.8|2026-03-25|페후 (이태훈)|수평 스와이프 실시간 seek 프리뷰 구현 — 드래그 시작 시 플레이어 일시정지, 드래그 중 _player.seek() 실시간 호출로 영상 프리뷰, 드래그 종료 시 재생 재개 (오디오 끊김 방지)|
457
|v4.9|2026-03-25|페후 (이태훈)|방향키 탐색 진행바 즉각 반영 — _seekPreviewPos 변수 추가, 키 입력 시 진행바 즉시 이동 (디바운스 400ms 완료 전에도 시각적 위치 반영)|
458
|v4.10|2026-03-25|페후 (이태훈)|컨트롤 숨김 시 터치 차단 — AnimatedOpacity를 IgnorePointer로 감싸 컨트롤 비표시 상태에서 진행바·버튼 터치 이벤트 완전 차단 (비디오 영역 탭으로 컨트롤 재표시는 정상 동작 유지)|
459
|v4.11|2026-03-25|페후 (이태훈)|재생 에러 오버레이 조건 수정 — stream.error를 duration==0일 때만 표시 (파일 로드 실패 시만 표시, 재생 중 발생하는 mpv 경고성 메시지는 무시), 500ms 지연 후 판단|
460
|v4.12|2026-03-25|페후 (이태훈)|수평 스와이프 볼륨 복원 버그 수정 — setVolume(0) 호출 시 stream.volume이 _volume을 0으로 덮어쓰는 문제 해결 (_horizDragSavedVolume에 드래그 시작 전 볼륨 저장 후 복원)|
461
|v4.13|2026-03-25|페후 (이태훈)|수평 스와이프 오디오 완전 차단 — setVolume 방식 대신 pause/resume 방식으로 변경 (드래그 중 pause로 오디오 버퍼 재생 방지, 드래그 종료 시 재생 여부에 따라 play 재개)|
462
|v4.14|2026-03-25|페후 (이태훈)|Android 플레이어 immersive 모드 적용 — initState에서 SystemChrome.setEnabledSystemUIMode(immersiveSticky) 호출, 플레이어 진입 시 시스템 UI(네비게이션 바·상태 바) 고정 숨김으로 컨트롤 표시/숨김 전환 시 MediaQuery.padding 변화에 의한 레이아웃 이탈 현상 해결, dispose 시 edgeToEdge로 복원|
463
|v4.15|2026-03-25|페후 (이태훈)|컨트롤 숨김 시 터치 차단 방식 변경 — IgnorePointer 래핑 방식 제거 (외부 GestureDetector 제스처까지 차단되는 문제 발생), Slider의 onChanged/onChangeStart/onChangeEnd를 _controlsVisible 조건부로 null 처리하는 방식으로 교체 (진행바만 비활성화, 스와이프 제스처 정상 동작 유지)|
464
|v4.16|2026-03-25|페후 (이태훈)|Android 뒤로가기 동작 개선 — PopScope 적용으로 시스템 뒤로가기 버튼 인터셉트, _saveAndPop()에서 재생 위치 await 저장 후 SystemNavigator.pop()으로 앱 완전 종료 (홈 화면이 아닌 DS File 등 이전 앱으로 복귀), PC는 기존 Navigator.pop() 유지|
465
|v4.17|2026-03-25|페후 (이태훈)|Android 홈 화면 최근 목록 숨김 — Android는 외부 앱(DS File 등)에서 인텐트로 직접 플레이어 실행하는 사용 패턴으로 최근 목록이 불필요, Platform.isAndroid 조건으로 최근 목록 및 전체 삭제 버튼 미표시 처리|
466
|v4.18|2026-03-25|페후 (이태훈)|Android 시스템 제스처 충돌 방지 엣지 데드존 추가 — 화면 좌/우/하단 32dp 이내에서 시작한 스와이프를 BBPlayer 제스처로 처리하지 않음 (_isEdgeTouch() 헬퍼, _gestureCancelled 플래그, 수직/수평 드래그 핸들러 모두 적용), 시스템 UI 표시용 엣지 스와이프와의 충돌 해결|
467
|v4.19|2026-03-25|페후 (이태훈)|SMI 자막 형식 지원 추가 — 자동 로드 확장자 목록 및 수동 로드 파일 선택 다이얼로그에 .smi 추가 (mpv 기반 media_kit이 SAMI 형식 네이티브 지원), 싱크 오프셋은 SRT와 타임스탬프 구조가 달라 미적용|
468
|v4.20|2026-03-25|페후 (이태훈)|3.4.7 재생 중 파일 교체 Android 제외 — Android는 외부 앱에서 인텐트로 직접 실행하는 사용 패턴으로 재생 중 파일 교체 불필요, 상단 바 파일 열기 버튼 및 Ctrl+O 단축키를 Windows/macOS 전용으로 제한|
469
|v4.21|2026-03-25|페후 (이태훈)|3.5.1 진행바 썸네일 미리보기 구현 — Windows/macOS 전용, 별도 _thumbPlayer 인스턴스로 메인 재생 중단 없이 seek+screenshot, 150ms 디바운스, LayoutBuilder로 슬라이더 실제 너비 계산, MouseRegion 호버 추적, 드래그 중 팝업 자동 숨김|
470
|v4.22|2026-03-25|페후 (이태훈)|3.5.4 드래그 앤 드롭 구현 — desktop_drop 패키지 추가, DropTarget으로 전체 화면 래핑(Android 제외), 드롭 위치(localPosition.dx)로 교체/추가 분기, 플레이리스트 열림 여부에 따라 좌측(파일 교체)/우측(목록 추가) 오버레이 UI, 다중 파일 드롭 지원|