implement video download
All checks were successful
Build and Push Multi-Arch Docker Image / build-and-push (push) Successful in 18m34s

needs check, if converted files can be run on device

Signed-off-by: Peter Siegmund <developer@mars3142.org>
This commit is contained in:
2026-02-01 11:39:02 +01:00
parent efd34616b1
commit 551226ead9
13 changed files with 392 additions and 48 deletions

View File

@@ -0,0 +1,77 @@
import 'package:cinema/common/dio_module.dart';
import 'package:cinema/common/video_downloader.dart';
import 'package:cinema/feature/poster/domain/movie.dart';
import 'package:cinema/feature/video/data/repositories/video_loader.dart';
import 'package:dio/dio.dart';
import 'package:injectable/injectable.dart';
@Injectable(as: VideoLoader)
class TmdbVideoLoader implements VideoLoader {
final Dio api;
final VideoDownloader _videoDownloader;
TmdbVideoLoader(@Named(dioAPI) this.api, this._videoDownloader);
@override
Future<String?> getYouTubeVideoId(int movieId, {String language = 'de'}) async {
try {
final response = await api.get('/movie/$movieId/videos?language=$language');
if (response.data != null && response.data['results'] != null) {
final results = response.data['results'] as List;
// Filtere nur YouTube Videos
final youtubeVideos = results.where((v) => v['site'] == 'YouTube').toList();
if (youtubeVideos.isEmpty) {
return null;
}
// Sortiere nach published_at absteigend (neueste zuerst)
youtubeVideos.sort((a, b) {
final dateA = DateTime.tryParse(a['published_at'] ?? '') ?? DateTime(1970);
final dateB = DateTime.tryParse(b['published_at'] ?? '') ?? DateTime(1970);
return dateB.compareTo(dateA);
});
// Suche den neuesten Trailer oder Teaser
for (final video in youtubeVideos) {
if (video['type'] == 'Trailer' || video['type'] == 'Teaser') {
return video['key'] as String?;
}
}
// Falls kein Trailer/Teaser, nimm das neueste YouTube Video
return youtubeVideos.first['key'] as String?;
}
} catch (e) {
print('Error fetching video for movie $movieId: $e');
}
return null;
}
@override
Future<bool> downloadVideo(Movie movie) async {
final videoId = await getYouTubeVideoId(movie.id);
if (videoId == null) {
print('No YouTube video found for movie ${movie.id} (${movie.title})');
return false;
}
// Check if already cached
if (await _videoDownloader.isCached(videoId)) {
print('Video already cached: ${movie.title} ($videoId)');
return true;
}
print('Downloading video: ${movie.title} ($videoId)...');
final path = await _videoDownloader.downloadAndResize(videoId);
if (path != null) {
print('Video cached successfully: ${movie.title} ($videoId)');
return true;
}
print('Failed to cache video: ${movie.title} ($videoId)');
return false;
}
}

View File

@@ -0,0 +1,7 @@
import 'package:cinema/feature/poster/domain/movie.dart';
abstract class VideoLoader {
Future<String?> getYouTubeVideoId(int movieId, {String language = 'de'});
Future<bool> downloadVideo(Movie movie);
}