computeManifests function
- ComputeManifestParams params
Used to be able to get both manifests at the same time.
Implementation
Future<VideoManifest> computeManifests(ComputeManifestParams params) async {
YoutubeExplode yt = YoutubeExplode();
List<Future> futures = [
yt.videos.streamsClient.getManifest(params.videoId),
];
if (params.closedCaptionsManifest == null) {
futures.add(yt.videos.closedCaptions.getManifest(
params.videoId,
formats: [ClosedCaptionFormat.vtt],
));
}
final manifests = await Future.wait(futures);
StreamManifest streamManifest = manifests.elementAt(0) as StreamManifest;
late ClosedCaptionManifest closedCaptionManifest;
if (params.closedCaptionsManifest != null) {
closedCaptionManifest = params.closedCaptionsManifest!;
} else {
closedCaptionManifest = manifests.elementAt(1) as ClosedCaptionManifest;
}
Map<String, ClosedCaptionTrackInfo> tracksByLanguage = {};
List<ClosedCaptionTrackInfo> ccTracks =
closedCaptionManifest.tracks.where((e) => !e.isAutoGenerated).toList();
List<ClosedCaptionTrackInfo> autoTracks =
closedCaptionManifest.tracks.where((e) => e.isAutoGenerated).toList();
for (ClosedCaptionTrackInfo track in [...ccTracks, ...autoTracks]) {
String shortCode = track.language.code.substring(0, 2);
tracksByLanguage.putIfAbsent(shortCode, () => track);
}
List<MapEntry<String, String>> entries = [];
if (!params.subtitlesCached) {
entries.addAll(
await Future.wait(
tracksByLanguage.values.map(
(trackInfo) async {
String shortCode = trackInfo.language.code.substring(0, 2);
String subtitles =
await yt.videos.closedCaptions.getSubTitles(trackInfo);
if (trackInfo.isAutoGenerated) {
subtitles = subtitles.replaceAllMapped(vttRegex, (match) {
String text = match.group(11) ?? '';
List<String> lines = text.split('\n');
String currentSubtitle =
subtitles.substring(match.start, match.end);
int position = currentSubtitle
.lastIndexOf(text)
.clamp(0, currentSubtitle.length);
String newSubtitle = currentSubtitle.replaceFirst(
text, lines.last.trim(), position);
return newSubtitle;
});
}
String metadata = trackInfo.isAutoGenerated
? 'YouTube - Auto - [$shortCode]'
: 'YouTube - CC - [$shortCode]';
return MapEntry(metadata, subtitles);
},
),
),
);
}
Map<String, String> subtitlesByLanguageCache = {};
for (MapEntry<String, String> entry in entries) {
subtitlesByLanguageCache.putIfAbsent(entry.key, () => entry.value);
}
return VideoManifest(
streamManifest: streamManifest,
closedCaptionManifest: closedCaptionManifest,
subtitlesByLanguageCache: subtitlesByLanguageCache,
);
}