mirror of
https://github.com/KRTirtho/spotube.git
synced 2025-09-13 07:55:18 +00:00
feat: implement NewPipe engine
This commit is contained in:
parent
f270b2ebb9
commit
09a141b472
@ -38,6 +38,7 @@ android {
|
||||
ndkVersion = "27.0.12077973"
|
||||
|
||||
compileOptions {
|
||||
coreLibraryDesugaringEnabled true
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
}
|
||||
@ -120,6 +121,8 @@ flutter {
|
||||
|
||||
def glanceVersion = "1.1.1"
|
||||
dependencies {
|
||||
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.1.4'
|
||||
|
||||
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.5.1'
|
||||
// other deps so just ignore
|
||||
implementation 'com.android.support:multidex:2.0.1'
|
||||
|
@ -51,6 +51,7 @@ import 'package:timezone/data/latest.dart' as tz;
|
||||
import 'package:window_manager/window_manager.dart';
|
||||
import 'package:shadcn_flutter/shadcn_flutter.dart';
|
||||
import 'package:yt_dlp_dart/yt_dlp_dart.dart';
|
||||
import 'package:flutter_new_pipe_extractor/flutter_new_pipe_extractor.dart';
|
||||
|
||||
Future<void> main(List<String> rawArgs) async {
|
||||
if (rawArgs.contains("web_view_title_bar")) {
|
||||
@ -78,6 +79,7 @@ Future<void> main(List<String> rawArgs) async {
|
||||
// force High Refresh Rate on some Android devices (like One Plus)
|
||||
if (kIsAndroid) {
|
||||
await FlutterDisplayMode.setHighRefreshRate();
|
||||
await NewPipeExtractor.init();
|
||||
}
|
||||
|
||||
if (!kIsWeb) {
|
||||
|
@ -18,6 +18,7 @@ import 'package:spotube/services/sourced_track/enums.dart';
|
||||
import 'package:flutter/widgets.dart' hide Table, Key, View;
|
||||
import 'package:spotube/modules/settings/color_scheme_picker_dialog.dart';
|
||||
import 'package:drift/native.dart';
|
||||
import 'package:spotube/services/youtube_engine/newpipe_engine.dart';
|
||||
import 'package:spotube/services/youtube_engine/youtube_explode_engine.dart';
|
||||
import 'package:spotube/services/youtube_engine/yt_dlp_engine.dart';
|
||||
import 'package:sqlite3/sqlite3.dart';
|
||||
|
@ -34,8 +34,7 @@ enum YoutubeClientEngine {
|
||||
YoutubeClientEngine.youtubeExplode =>
|
||||
YouTubeExplodeEngine.isAvailableForPlatform,
|
||||
YoutubeClientEngine.ytDlp => YtDlpEngine.isAvailableForPlatform,
|
||||
// TODO: Implement new pipe support
|
||||
YoutubeClientEngine.newPipe => false,
|
||||
YoutubeClientEngine.newPipe => NewPipeEngine.isAvailableForPlatform,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:spotube/models/database/database.dart';
|
||||
import 'package:spotube/provider/user_preferences/user_preferences_provider.dart';
|
||||
import 'package:spotube/services/youtube_engine/newpipe_engine.dart';
|
||||
import 'package:spotube/services/youtube_engine/youtube_explode_engine.dart';
|
||||
import 'package:spotube/services/youtube_engine/yt_dlp_engine.dart';
|
||||
|
||||
@ -9,8 +10,9 @@ final youtubeEngineProvider = Provider((ref) {
|
||||
userPreferencesProvider.select((value) => value.youtubeClientEngine),
|
||||
);
|
||||
|
||||
if (engineMode == YoutubeClientEngine.newPipe) {
|
||||
throw UnimplementedError();
|
||||
if (engineMode == YoutubeClientEngine.newPipe &&
|
||||
NewPipeEngine.isAvailableForPlatform) {
|
||||
return NewPipeEngine();
|
||||
} else if (engineMode == YoutubeClientEngine.ytDlp &&
|
||||
YtDlpEngine.isAvailableForPlatform) {
|
||||
return YtDlpEngine();
|
||||
|
109
lib/services/youtube_engine/newpipe_engine.dart
Normal file
109
lib/services/youtube_engine/newpipe_engine.dart
Normal file
@ -0,0 +1,109 @@
|
||||
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,
|
||||
stream.quality,
|
||||
[],
|
||||
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<StreamManifest> getStreamManifest(String videoId) async {
|
||||
final video = await NewPipeExtractor.getVideoInfo(videoId);
|
||||
|
||||
final streams =
|
||||
video.audioStreams.map((stream) => _parseAudioStream(stream, videoId));
|
||||
|
||||
return StreamManifest(streams);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Video> getVideo(String videoId) async {
|
||||
final video = await NewPipeExtractor.getVideoInfo(videoId);
|
||||
|
||||
return _parseVideo(video);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<(Video, StreamManifest)> getVideoWithStreamInfo(String videoId) async {
|
||||
final video = await NewPipeExtractor.getVideoInfo(videoId);
|
||||
|
||||
final streams =
|
||||
video.audioStreams.map((stream) => _parseAudioStream(stream, videoId));
|
||||
|
||||
return (_parseVideo(video), StreamManifest(streams));
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<Video>> searchVideos(String query) async {
|
||||
final results = await NewPipeExtractor.search(
|
||||
query,
|
||||
contentFilters: [SearchContentFilters.musicSongs],
|
||||
);
|
||||
|
||||
final resultsWithVideos = results
|
||||
.whereType<VideoSearchResultItem>()
|
||||
.map((e) => _parseVideoResult(e))
|
||||
.toList();
|
||||
|
||||
return resultsWithVideos;
|
||||
}
|
||||
}
|
13
pubspec.lock
13
pubspec.lock
@ -914,6 +914,13 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.4.3"
|
||||
flutter_new_pipe_extractor:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
path: "../flutter_new_pipe_extractor"
|
||||
relative: true
|
||||
source: path
|
||||
version: "0.1.0"
|
||||
flutter_plugin_android_lifecycle:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -1210,13 +1217,13 @@ packages:
|
||||
source: hosted
|
||||
version: "3.2.1"
|
||||
http_parser:
|
||||
dependency: transitive
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: http_parser
|
||||
sha256: "76d306a1c3afb33fe82e2bbacad62a61f409b5634c915fceb0d799de1a913360"
|
||||
sha256: "178d74305e7866013777bab2c3d8726205dc5a4dd935297175b19a23a2e66571"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.1.1"
|
||||
version: "4.1.2"
|
||||
image:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -144,6 +144,9 @@ dependencies:
|
||||
git:
|
||||
url: https://github.com/KRTirtho/yt_dlp_dart.git
|
||||
ref: e2d82305fab18566408d6f8758361017d1640c3d
|
||||
flutter_new_pipe_extractor:
|
||||
path: ../flutter_new_pipe_extractor
|
||||
http_parser: ^4.1.2
|
||||
|
||||
dev_dependencies:
|
||||
build_runner: ^2.4.13
|
||||
|
Loading…
Reference in New Issue
Block a user