import 'package:flutter_new_pipe_extractor/flutter_new_pipe_extractor.dart' hide Engagement; import 'package:spotube/services/youtube_engine/youtube_engine.dart'; import 'package:spotube/utils/platform.dart'; import 'package:youtube_explode_dart/youtube_explode_dart.dart'; import 'package:http_parser/http_parser.dart'; class NewPipeEngine implements YouTubeEngine { static bool get isAvailableForPlatform => kIsAndroid; AudioOnlyStreamInfo _parseAudioStream(AudioStream stream, String videoId) { return AudioOnlyStreamInfo( VideoId(videoId), stream.itag, Uri.parse(stream.content), StreamContainer.parse(stream.mediaFormat!.mimeType.split("/").last), FileSize.unknown, Bitrate(stream.bitrate), stream.codec, switch (stream.bitrate) { > 130 * 1024 => "high", > 64 * 1024 => "medium", _ => "low", }, [], MediaType.parse(stream.mediaFormat!.mimeType), null, ); } Video _parseVideo(VideoInfo info) { return Video( VideoId(info.id), info.name, info.uploaderName, ChannelId(info.uploaderUrl), info.uploadDate.offsetDateTime, info.uploadDate.offsetDateTime.toString(), info.uploadDate.offsetDateTime, info.description.content ?? "", Duration(seconds: info.duration), ThumbnailSet(info.id), info.tags, Engagement( info.viewCount, info.likeCount, info.dislikeCount, ), !info.streamType.name.toLowerCase().contains("live"), ); } Video _parseVideoResult(VideoSearchResultItem info) { final id = Uri.parse(info.url).queryParameters["v"]!; return Video( VideoId(id), info.name, info.uploaderName, ChannelId(info.uploaderUrl), info.uploadDate?.offsetDateTime, info.uploadDate?.offsetDateTime.toString(), info.uploadDate?.offsetDateTime, info.shortDescription ?? "", Duration(seconds: info.duration), ThumbnailSet(id), [], Engagement(info.viewCount, null, null), !info.streamType.name.toLowerCase().contains("live"), ); } @override Future getStreamManifest(String videoId) async { final video = await NewPipeExtractor.getVideoInfo(videoId); final streams = video.audioStreams.map((stream) => _parseAudioStream(stream, videoId)); return StreamManifest(streams); } @override Future