웹 브라우저: 다른 화면으로 가면 페이지의 동영상 · 소리 멈춤

브라우저에서 [다운로드] → 목록 보기 (또는 플레이어 · 설정 등) 로 가면 가려진 브라우저에서
YouTube 가 계속 재생되어 소리만 났다. 브라우저 위에 다른 화면이 올라오면 (RouteAware.didPushNext)
페이지의 video · audio 를 멈춘다 (WebNav.pauseMedia, Edge · Chrome · Android 웹뷰 공통).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
main
RyuJongJin 2026-10-03 04:49:33 +09:00
parent 39f65f414c
commit 07ec8cd4a5
3 changed files with 42 additions and 1 deletions

View File

@ -507,6 +507,7 @@ class JjCapCutApp extends StatelessWidget {
theme: buildTheme(),
navigatorKey: navigatorKey,
scaffoldMessengerKey: messengerKey,
navigatorObservers: [browserRouteObserver],
// 모든 화면에: 환경 설정 · 종료 버튼이 쓸 것 + 끌어다 놓은 동영상을 목록에 추가
builder: (context, child) => AppScope(
controller: controller,

View File

@ -30,8 +30,17 @@ abstract class WebNav {
/// YouTube · Google 로그인 쿠키를 yt-dlp 용 cookies.txt 로 내보내기
Future<void> exportCookies();
/// 페이지의 동영상 · 소리 멈추기 (다른 화면으로 갈 때)
Future<void> pauseMedia();
}
/// 페이지의 모든 동영상 · 소리를 멈추는 스크립트
const pauseMediaScript = "document.querySelectorAll('video,audio').forEach(function(m){try{m.pause()}catch(e){}})";
/// 화면 이동 알림 (브라우저 위에 다른 화면이 올라오면 동영상을 멈춘다). MaterialApp.navigatorObservers 에 넣는다.
final browserRouteObserver = RouteObserver<ModalRoute<void>>();
/// 웹뷰 → 화면으로 알리는 통로
class BrowserHost {
final void Function(String url) onUrl;
@ -97,7 +106,7 @@ class BrowserPage extends StatefulWidget {
}
}
class _BrowserPageState extends State<BrowserPage> {
class _BrowserPageState extends State<BrowserPage> with RouteAware {
late String _url = widget.initialUrl ?? widget.c.settings.homeUrl;
String _title = '';
double _progress = 1;
@ -138,8 +147,22 @@ class _BrowserPageState extends State<BrowserPage> {
BrowserPage._open++;
}
@override
void didChangeDependencies() {
super.didChangeDependencies();
final route = ModalRoute.of(context);
if (route != null) browserRouteObserver.subscribe(this, route);
}
/// 다운로드 목록 · 플레이어 · 설정 등이 위에 올라왔다: 보던 동영상을 멈춘다 (가려진 채 소리만 나지 않게)
@override
void didPushNext() {
_nav?.pauseMedia();
}
@override
void dispose() {
browserRouteObserver.unsubscribe(this);
BrowserPage._open--;
_address.dispose();
_addressFocus.dispose();
@ -492,6 +515,13 @@ class _InAppNav implements WebNav {
final String dataDir;
_InAppNav(this.c, this.env, this.dataDir);
@override
Future<void> pauseMedia() async {
try {
await c.evaluateJavascript(source: pauseMediaScript);
} catch (_) {}
}
static const _cookieSites = [
'https://www.youtube.com/',
'https://m.youtube.com/',
@ -642,6 +672,13 @@ class _CefNav implements WebNav {
final String dataDir;
_CefNav(this.c, this.dataDir);
@override
Future<void> pauseMedia() async {
try {
await c.evaluateJavascript(pauseMediaScript);
} catch (_) {}
}
/// YouTube · Google 쿠키를 yt-dlp 용 cookies.txt 로 (Edge 와 같은 파일 - 지금 쓰는 엔진의 로그인이 쓰인다).
/// Chrome 엔진은 쿠키의 이름 · 값만 알려 주므로 만료 · 보안 표시는 기본값으로 적는다.
@override

View File

@ -40,6 +40,9 @@ class _Backend implements DownloadBackend {
}
class _Nav implements WebNav {
int paused = 0;
@override
Future<void> pauseMedia() async => paused++;
final loads = <String>[];
@override
Future<void> load(String url) async => loads.add(url);