jbilcke-hf HF Staff commited on
Commit
7a46537
·
1 Parent(s): 3cc7c13

improve orientation switch

Browse files
api_core.py CHANGED
@@ -619,7 +619,7 @@ Your caption:"""
619
 
620
  # Use the same logic as regular video generation but with thumbnail settings
621
  try:
622
- logger.info(f"[{request_id}] Generating thumbnail for video {video_id} with seed {seed}")
623
 
624
  start_time = time.time()
625
  # Rest of thumbnail generation logic same as regular video but with optimized settings
@@ -684,16 +684,14 @@ Your caption:"""
684
  if orientation == 'PORTRAIT' and width > height:
685
  # Swap width and height for portrait orientation
686
  width, height = height, width
687
- logger.info(f"Orientation: {orientation}, swapped dimensions to width={width}, height={height}")
688
  elif orientation == 'LANDSCAPE' and height > width:
689
  # Swap height and width for landscape orientation
690
  height, width = width, height
691
- logger.info(f"Orientation: {orientation}, swapped dimensions to width={width}, height={height}")
692
  else:
693
- logger.info(f"Orientation: {orientation}, using original dimensions width={width}, height={height}")
694
-
695
- # Log the user role and config values being used
696
- logger.info(f"Using config values: width={width}, height={height}, num_frames={num_frames}, steps={num_inference_steps}, fps={frame_rate} | role: {user_role}")
697
 
698
  # Generate the video with standard settings
699
  return await self._generate_video_content(
@@ -720,7 +718,7 @@ Your caption:"""
720
  request_id = options.get('request_id', str(uuid.uuid4())[:8]) # Get or generate request ID
721
  video_id = options.get('video_id', 'unknown')
722
 
723
- logger.info(f"[{request_id}] Generating {'thumbnail' if is_thumbnail else 'video'} for video {video_id} with seed {seed}")
724
 
725
  json_payload = {
726
  "inputs": {
 
619
 
620
  # Use the same logic as regular video generation but with thumbnail settings
621
  try:
622
+ # logger.info(f"[{request_id}] Generating thumbnail for video {video_id} with seed {seed}")
623
 
624
  start_time = time.time()
625
  # Rest of thumbnail generation logic same as regular video but with optimized settings
 
684
  if orientation == 'PORTRAIT' and width > height:
685
  # Swap width and height for portrait orientation
686
  width, height = height, width
687
+ # logger.info(f"Orientation: {orientation}, swapped dimensions to width={width}, height={height}")
688
  elif orientation == 'LANDSCAPE' and height > width:
689
  # Swap height and width for landscape orientation
690
  height, width = width, height
691
+ #logger.info(f"Orientation: {orientation}, swapped dimensions to width={width}, height={height}, steps={num_inference_steps}, fps={frame_rate} | role: {user_role}")
692
  else:
693
+ #logger.info(f"Orientation: {orientation}, using original dimensions width={width}, height={height}, steps={num_inference_steps}, fps={frame_rate} | role: {user_role}")
694
+ pass
 
 
695
 
696
  # Generate the video with standard settings
697
  return await self._generate_video_content(
 
718
  request_id = options.get('request_id', str(uuid.uuid4())[:8]) # Get or generate request ID
719
  video_id = options.get('video_id', 'unknown')
720
 
721
+ # logger.info(f"[{request_id}] Generating {'thumbnail' if is_thumbnail else 'video'} for video {video_id} with seed {seed}")
722
 
723
  json_payload = {
724
  "inputs": {
build/web/flutter_bootstrap.js CHANGED
@@ -39,6 +39,6 @@ _flutter.buildConfig = {"engineRevision":"382be0028d370607f76215a9be322e5514b263
39
 
40
  _flutter.loader.load({
41
  serviceWorkerSettings: {
42
- serviceWorkerVersion: "683227308"
43
  }
44
  });
 
39
 
40
  _flutter.loader.load({
41
  serviceWorkerSettings: {
42
+ serviceWorkerVersion: "1197636580"
43
  }
44
  });
build/web/flutter_service_worker.js CHANGED
@@ -3,11 +3,11 @@ const MANIFEST = 'flutter-app-manifest';
3
  const TEMP = 'flutter-temp-cache';
4
  const CACHE_NAME = 'flutter-app-cache';
5
 
6
- const RESOURCES = {"flutter_bootstrap.js": "05bd8824501c20bb663a0f9ab56f5c49",
7
  "version.json": "b5eaae4fc120710a3c35125322173615",
8
  "index.html": "cd2094e3989e3eb0424e47d7d188c298",
9
  "/": "cd2094e3989e3eb0424e47d7d188c298",
10
- "main.dart.js": "62f7660e444a6aa729a12c4639b95395",
11
  "flutter.js": "83d881c1dbb6d6bcd6b42e274605b69c",
12
  "aitube.svg": "26140ba0d153b213b122bc6ebcc17f6c",
13
  "favicon.png": "c8a183c516004e648a7bac7497c89b97",
 
3
  const TEMP = 'flutter-temp-cache';
4
  const CACHE_NAME = 'flutter-app-cache';
5
 
6
+ const RESOURCES = {"flutter_bootstrap.js": "2e5faa3ab3c446c3c3eaa2ce252f366a",
7
  "version.json": "b5eaae4fc120710a3c35125322173615",
8
  "index.html": "cd2094e3989e3eb0424e47d7d188c298",
9
  "/": "cd2094e3989e3eb0424e47d7d188c298",
10
+ "main.dart.js": "14a165f5350b8bcff180f1cf376cf819",
11
  "flutter.js": "83d881c1dbb6d6bcd6b42e274605b69c",
12
  "aitube.svg": "26140ba0d153b213b122bc6ebcc17f6c",
13
  "favicon.png": "c8a183c516004e648a7bac7497c89b97",
build/web/index.html CHANGED
@@ -156,7 +156,7 @@
156
  </script>
157
 
158
  <!-- Add version parameter for cache busting -->
159
- <script src="flutter_bootstrap.js?v=1746635426" async></script>
160
 
161
  <!-- Add cache busting script -->
162
  <script>
 
156
  </script>
157
 
158
  <!-- Add version parameter for cache busting -->
159
+ <script src="flutter_bootstrap.js?v=1746641479" async></script>
160
 
161
  <!-- Add cache busting script -->
162
  <script>
build/web/main.dart.js CHANGED
The diff for this file is too large to render. See raw diff
 
lib/screens/video_screen.dart CHANGED
@@ -444,7 +444,9 @@ class _VideoScreenState extends State<VideoScreen> {
444
  )
445
  : Column(
446
  children: [
447
- _buildMainContent(),
 
 
448
  if (Configuration.instance.showChatInVideoView) ...[
449
  const SizedBox(height: 16),
450
  Expanded(
@@ -466,23 +468,27 @@ class _VideoScreenState extends State<VideoScreen> {
466
  }
467
 
468
  Widget _buildMainContent() {
469
- return SingleChildScrollView(
470
- padding: const EdgeInsets.all(16),
471
- child: Column(
472
- crossAxisAlignment: CrossAxisAlignment.start,
473
- children: [
474
- // Video Player with unique key to force recreation when needed
475
- VideoPlayerWidget(
476
- key: _videoPlayerKey,
477
- video: _videoData,
478
- initialThumbnailUrl: _videoData.thumbnailUrl,
479
- autoPlay: true,
480
- ),
481
- const SizedBox(height: 16),
 
 
 
482
 
483
- // Collapsible Title and Description Section
484
- _buildCollapsibleInfoSection(),
485
- ],
 
486
  ),
487
  );
488
  }
 
444
  )
445
  : Column(
446
  children: [
447
+ Expanded(
448
+ child: _buildMainContent(),
449
+ ),
450
  if (Configuration.instance.showChatInVideoView) ...[
451
  const SizedBox(height: 16),
452
  Expanded(
 
468
  }
469
 
470
  Widget _buildMainContent() {
471
+ return Container(
472
+ color: Theme.of(context).scaffoldBackgroundColor,
473
+ child: SingleChildScrollView(
474
+ padding: const EdgeInsets.all(16),
475
+ physics: const AlwaysScrollableScrollPhysics(),
476
+ child: Column(
477
+ crossAxisAlignment: CrossAxisAlignment.start,
478
+ children: [
479
+ // Video Player with unique key to force recreation when needed
480
+ VideoPlayerWidget(
481
+ key: _videoPlayerKey,
482
+ video: _videoData,
483
+ initialThumbnailUrl: _videoData.thumbnailUrl,
484
+ autoPlay: true,
485
+ ),
486
+ const SizedBox(height: 16),
487
 
488
+ // Collapsible Title and Description Section
489
+ _buildCollapsibleInfoSection(),
490
+ ],
491
+ ),
492
  ),
493
  );
494
  }
lib/widgets/video_player/video_player_widget.dart CHANGED
@@ -73,6 +73,12 @@ class _VideoPlayerWidgetState extends State<VideoPlayerWidget> with WidgetsBindi
73
 
74
  /// Current orientation
75
  VideoOrientation _currentOrientation = VideoOrientation.LANDSCAPE;
 
 
 
 
 
 
76
 
77
  @override
78
  void initState() {
@@ -134,11 +140,33 @@ class _VideoPlayerWidgetState extends State<VideoPlayerWidget> with WidgetsBindi
134
  Future<void> _initializePlayer() async {
135
  if (_isDisposed) return;
136
 
137
- // Get initial orientation
138
  final mediaQuery = MediaQuery.of(context);
139
- _currentOrientation = mediaQuery.orientation == Orientation.landscape
140
- ? VideoOrientation.LANDSCAPE
141
- : VideoOrientation.PORTRAIT;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
142
 
143
  _playbackController = PlaybackController();
144
  _playbackController.isLoading = true;
@@ -160,6 +188,9 @@ class _VideoPlayerWidgetState extends State<VideoPlayerWidget> with WidgetsBindi
160
 
161
  // Initialize buffer manager with current orientation
162
  await _bufferManager.initialize();
 
 
 
163
  }
164
 
165
  if (!_isDisposed && mounted) {
@@ -272,8 +303,8 @@ class _VideoPlayerWidgetState extends State<VideoPlayerWidget> with WidgetsBindi
272
  debugPrint('Error playing clip: $e');
273
  if (!_isDisposed) {
274
  if (!_isDisposed && mounted) {
275
- setState(() => _playbackController.isLoading = true);
276
- }
277
  await Future.delayed(const Duration(milliseconds: 500));
278
  }
279
  }
@@ -366,35 +397,41 @@ class _VideoPlayerWidgetState extends State<VideoPlayerWidget> with WidgetsBindi
366
  // Dispose controllers and timers
367
  _playbackController.dispose();
368
  _bufferManager.dispose();
 
369
 
370
  super.dispose();
371
  }
372
 
373
  @override
374
  Widget build(BuildContext context) {
 
 
 
 
 
375
  return LayoutBuilder(
376
  builder: (context, constraints) {
377
- // Determine orientation based on form factor rather than device orientation
378
- // This ensures proper behavior on desktop platforms
379
  VideoOrientation newOrientation;
380
 
381
- if (kIsWeb || !defaultTargetPlatform.isMobile) {
382
- // For web and desktop platforms, use form factor (width vs height) to determine orientation
383
- newOrientation = constraints.maxWidth > constraints.maxHeight
384
- ? VideoOrientation.LANDSCAPE
385
- : VideoOrientation.PORTRAIT;
386
 
387
- // Add a small buffer so we don't change orientation too frequently on borderline cases
388
- if (newOrientation == VideoOrientation.LANDSCAPE &&
389
- constraints.maxWidth / constraints.maxHeight < 1.05) {
390
- newOrientation = _currentOrientation;
391
- } else if (newOrientation == VideoOrientation.PORTRAIT &&
392
- constraints.maxHeight / constraints.maxWidth < 1.05) {
393
  newOrientation = _currentOrientation;
394
  }
395
  } else {
396
- // For mobile platforms, use the device orientation
397
- final orientation = MediaQuery.of(context).orientation;
398
  newOrientation = orientation == Orientation.landscape
399
  ? VideoOrientation.LANDSCAPE
400
  : VideoOrientation.PORTRAIT;
@@ -402,21 +439,87 @@ class _VideoPlayerWidgetState extends State<VideoPlayerWidget> with WidgetsBindi
402
 
403
  // Check if orientation changed
404
  if (newOrientation != _currentOrientation) {
405
- debugPrint('Orientation changed to ${newOrientation.name} (form factor: ${constraints.maxWidth}x${constraints.maxHeight})');
406
- _currentOrientation = newOrientation;
 
407
 
408
- // Update buffer manager orientation (without awaiting to avoid blocking UI)
409
- Future.microtask(() async {
410
- if (!_isDisposed && mounted) {
411
- await _bufferManager.updateOrientation(newOrientation);
412
- }
413
- });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
414
  }
415
 
416
  // Video player layout
417
  final controller = _playbackController.currentController;
418
  final aspectRatio = controller?.value.aspectRatio ?? 16/9;
419
- final playerHeight = constraints.maxWidth / aspectRatio;
 
 
 
 
 
 
 
 
 
 
420
 
421
  return SizedBox(
422
  width: constraints.maxWidth,
 
73
 
74
  /// Current orientation
75
  VideoOrientation _currentOrientation = VideoOrientation.LANDSCAPE;
76
+
77
+ /// Last time orientation was changed
78
+ DateTime _lastOrientationChange = DateTime.now();
79
+
80
+ /// Timer for debouncing orientation changes
81
+ Timer? _orientationDebounceTimer;
82
 
83
  @override
84
  void initState() {
 
140
  Future<void> _initializePlayer() async {
141
  if (_isDisposed) return;
142
 
143
+ // Determine initial orientation based on platform
144
  final mediaQuery = MediaQuery.of(context);
145
+ if (kIsWeb) {
146
+ // For web, use screen dimensions to determine initial orientation
147
+ final screenWidth = mediaQuery.size.width;
148
+ final screenHeight = mediaQuery.size.height;
149
+ final aspectRatio = screenWidth / screenHeight;
150
+
151
+ // debugPrint('Initial screen size: ${screenWidth.toInt()}x${screenHeight.toInt()}, aspect ratio: ${aspectRatio.toStringAsFixed(2)}');
152
+
153
+ // Set initial orientation based on aspect ratio
154
+ if (aspectRatio > 1.2) {
155
+ _currentOrientation = VideoOrientation.LANDSCAPE;
156
+ } else if (aspectRatio < 0.8) {
157
+ _currentOrientation = VideoOrientation.PORTRAIT;
158
+ } else {
159
+ // Default to landscape for square-ish windows
160
+ _currentOrientation = VideoOrientation.LANDSCAPE;
161
+ }
162
+
163
+ // debugPrint('Initial orientation set to: ${_currentOrientation.name}');
164
+ } else {
165
+ // For mobile, use device orientation
166
+ _currentOrientation = mediaQuery.orientation == Orientation.landscape
167
+ ? VideoOrientation.LANDSCAPE
168
+ : VideoOrientation.PORTRAIT;
169
+ }
170
 
171
  _playbackController = PlaybackController();
172
  _playbackController.isLoading = true;
 
188
 
189
  // Initialize buffer manager with current orientation
190
  await _bufferManager.initialize();
191
+
192
+ // Update orientation after initialization
193
+ await _bufferManager.updateOrientation(_currentOrientation);
194
  }
195
 
196
  if (!_isDisposed && mounted) {
 
303
  debugPrint('Error playing clip: $e');
304
  if (!_isDisposed) {
305
  if (!_isDisposed && mounted) {
306
+ setState(() => _playbackController.isLoading = true);
307
+ }
308
  await Future.delayed(const Duration(milliseconds: 500));
309
  }
310
  }
 
397
  // Dispose controllers and timers
398
  _playbackController.dispose();
399
  _bufferManager.dispose();
400
+ _orientationDebounceTimer?.cancel();
401
 
402
  super.dispose();
403
  }
404
 
405
  @override
406
  Widget build(BuildContext context) {
407
+ // Get the actual screen/window dimensions from MediaQuery
408
+ final mediaQuery = MediaQuery.of(context);
409
+ final screenWidth = mediaQuery.size.width;
410
+ final screenHeight = mediaQuery.size.height;
411
+
412
  return LayoutBuilder(
413
  builder: (context, constraints) {
414
+ // Determine orientation based on the screen dimensions rather than the constraints
415
+ // This avoids issues with infinite heights in ScrollViews
416
  VideoOrientation newOrientation;
417
 
418
+ if (kIsWeb) {
419
+ // Use the screen dimensions to determine orientation
420
+ // This is more reliable than constraints in scrollable containers
421
+ double aspectRatio = screenWidth / screenHeight;
422
+ // debugPrint('Screen size: ${screenWidth.toInt()}x${screenHeight.toInt()}, aspect ratio: ${aspectRatio.toStringAsFixed(2)}');
423
 
424
+ if (aspectRatio > 1.2) {
425
+ newOrientation = VideoOrientation.LANDSCAPE;
426
+ } else if (aspectRatio < 0.8) {
427
+ newOrientation = VideoOrientation.PORTRAIT;
428
+ } else {
429
+ // In middle zone (near square), maintain current orientation for stability
430
  newOrientation = _currentOrientation;
431
  }
432
  } else {
433
+ // For mobile platforms, still use the device orientation
434
+ final orientation = mediaQuery.orientation;
435
  newOrientation = orientation == Orientation.landscape
436
  ? VideoOrientation.LANDSCAPE
437
  : VideoOrientation.PORTRAIT;
 
439
 
440
  // Check if orientation changed
441
  if (newOrientation != _currentOrientation) {
442
+ // Ensure we don't change orientation too frequently
443
+ final now = DateTime.now();
444
+ final timeSinceLastChange = now.difference(_lastOrientationChange);
445
 
446
+ // Debug log the orientation change request with more details
447
+ // debugPrint('Orientation change request: ${_currentOrientation.name} -> ${newOrientation.name}');
448
+ // debugPrint(' • Current orientation: ${_currentOrientation.name}');
449
+ // debugPrint(' • New orientation: ${newOrientation.name}');
450
+ // debugPrint(' • Screen size: ${screenWidth.toInt()}x${screenHeight.toInt()}');
451
+ // debugPrint(' • Aspect ratio: ${(screenWidth / screenHeight).toStringAsFixed(2)}');
452
+ // debugPrint(' • Time since last change: ${timeSinceLastChange.inMilliseconds}ms');
453
+
454
+ // Cancel any pending orientation change
455
+ _orientationDebounceTimer?.cancel();
456
+
457
+ if (timeSinceLastChange.inMilliseconds >= 500) {
458
+ // debugPrint('Applying immediate orientation change to ${newOrientation.name}');
459
+
460
+ // Force immediate orientation change
461
+ setState(() {
462
+ _currentOrientation = newOrientation;
463
+ _lastOrientationChange = now;
464
+ });
465
+
466
+ // Update buffer manager orientation
467
+ _bufferManager.updateOrientation(newOrientation);
468
+ } else {
469
+ // For recent changes, set a short timer to check if the orientation remains stable
470
+ _orientationDebounceTimer = Timer(const Duration(milliseconds: 800), () {
471
+ if (!_isDisposed && mounted) {
472
+ // Get the latest screen dimensions
473
+ final latestMediaQuery = MediaQuery.of(context);
474
+ final latestWidth = latestMediaQuery.size.width;
475
+ final latestHeight = latestMediaQuery.size.height;
476
+ final latestAspectRatio = latestWidth / latestHeight;
477
+
478
+ // debugPrint('Delayed check - screen size: ${latestWidth.toInt()}x${latestHeight.toInt()}, ratio: ${latestAspectRatio.toStringAsFixed(2)}');
479
+
480
+ // Determine if the orientation is still requesting the same change
481
+ VideoOrientation latestOrientation;
482
+ if (latestAspectRatio > 1.2) {
483
+ latestOrientation = VideoOrientation.LANDSCAPE;
484
+ } else if (latestAspectRatio < 0.8) {
485
+ latestOrientation = VideoOrientation.PORTRAIT;
486
+ } else {
487
+ latestOrientation = _currentOrientation;
488
+ }
489
+
490
+ // Only apply the change if the orientation is still the same as requested
491
+ if (latestOrientation == newOrientation && _currentOrientation != newOrientation) {
492
+ // debugPrint('Applying delayed orientation change to ${newOrientation.name}');
493
+
494
+ if (!_isDisposed && mounted) {
495
+ setState(() {
496
+ _currentOrientation = newOrientation;
497
+ _lastOrientationChange = DateTime.now();
498
+ });
499
+
500
+ // Update buffer manager orientation
501
+ _bufferManager.updateOrientation(newOrientation);
502
+ }
503
+ }
504
+ }
505
+ });
506
+ }
507
  }
508
 
509
  // Video player layout
510
  final controller = _playbackController.currentController;
511
  final aspectRatio = controller?.value.aspectRatio ?? 16/9;
512
+
513
+ // Calculate player height based on the available width from constraints
514
+ // (which will be finite in the row/column layout)
515
+ double playerHeight = constraints.maxWidth / aspectRatio;
516
+
517
+ // Safety check - if width was somehow infinite or the result is invalid
518
+ if (!constraints.maxWidth.isFinite || !playerHeight.isFinite) {
519
+ // Use a percentage of screen height as fallback
520
+ playerHeight = screenHeight * 0.4;
521
+ debugPrint('Using fallback height: $playerHeight (percentage of screen height)');
522
+ }
523
 
524
  return SizedBox(
525
  width: constraints.maxWidth,