mirror of
https://github.com/TeamNewPipe/NewPipeExtractor.git
synced 2025-01-09 19:10:33 +05:30
[YouTube] Add support for extracting auto-translated captions
Closes TeamNewPipe/NewPipeExtractor#977 Based on and adresses TeamNewPipe/NewPipe#8023
This commit is contained in:
parent
fafd471606
commit
ff030ad297
@ -476,6 +476,7 @@ public class PeertubeStreamExtractor extends StreamExtractor {
|
||||
.setMediaFormat(fmt)
|
||||
.setLanguageCode(languageCode)
|
||||
.setAutoGenerated(false)
|
||||
.setAutoTranslated(false)
|
||||
.build());
|
||||
}
|
||||
}
|
||||
|
@ -665,7 +665,8 @@ public class YoutubeStreamExtractor extends StreamExtractor {
|
||||
|
||||
@Override
|
||||
@Nonnull
|
||||
public List<SubtitlesStream> getSubtitles(final MediaFormat format) throws ParsingException {
|
||||
public List<SubtitlesStream> getSubtitles(@Nonnull final MediaFormat format)
|
||||
throws ParsingException {
|
||||
assertPageFetched();
|
||||
|
||||
// We cannot store the subtitles list because the media format may change
|
||||
@ -673,13 +674,12 @@ public class YoutubeStreamExtractor extends StreamExtractor {
|
||||
final JsonObject renderer = playerResponse.getObject("captions")
|
||||
.getObject("playerCaptionsTracklistRenderer");
|
||||
final JsonArray captionsArray = renderer.getArray("captionTracks");
|
||||
// TODO: use this to apply auto translation to different language from a source language
|
||||
// final JsonArray autoCaptionsArray = renderer.getArray("translationLanguages");
|
||||
|
||||
for (int i = 0; i < captionsArray.size(); i++) {
|
||||
final String languageCode = captionsArray.getObject(i).getString("languageCode");
|
||||
final String baseUrl = captionsArray.getObject(i).getString("baseUrl");
|
||||
final String vssId = captionsArray.getObject(i).getString("vssId");
|
||||
final JsonObject caption = captionsArray.getObject(i);
|
||||
final String languageCode = caption.getString("languageCode");
|
||||
final String baseUrl = caption.getString("baseUrl");
|
||||
final String vssId = caption.getString("vssId");
|
||||
|
||||
if (languageCode != null && baseUrl != null && vssId != null) {
|
||||
final boolean isAutoGenerated = vssId.startsWith("a.");
|
||||
@ -694,7 +694,24 @@ public class YoutubeStreamExtractor extends StreamExtractor {
|
||||
.setMediaFormat(format)
|
||||
.setLanguageCode(languageCode)
|
||||
.setAutoGenerated(isAutoGenerated)
|
||||
.setAutoTranslated(false)
|
||||
.build());
|
||||
if (i == 0 && caption.getBoolean("isTranslatable")
|
||||
&& renderer.has("translationLanguages")) {
|
||||
final JsonArray languages = renderer.getArray("translationLanguages");
|
||||
for (int j = 0; j < languages.size(); j++) {
|
||||
final JsonObject lang = languages.getObject(j);
|
||||
final String tLanguageCode = lang.getString("languageCode");
|
||||
subtitlesToReturn.add(new SubtitlesStream.Builder()
|
||||
.setContent(cleanUrl + "&fmt=" + format.getSuffix()
|
||||
+ "&tlang=" + tLanguageCode, true)
|
||||
.setMediaFormat(format)
|
||||
.setLanguageCode(tLanguageCode)
|
||||
.setAutoGenerated(isAutoGenerated)
|
||||
.setAutoTranslated(true)
|
||||
.build());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -14,6 +14,7 @@ public final class SubtitlesStream extends Stream {
|
||||
private final MediaFormat format;
|
||||
private final Locale locale;
|
||||
private final boolean autoGenerated;
|
||||
private final boolean autoTranslated;
|
||||
private final String code;
|
||||
|
||||
/**
|
||||
@ -32,6 +33,7 @@ public final class SubtitlesStream extends Stream {
|
||||
private String languageCode;
|
||||
// Use of the Boolean class instead of the primitive type needed for setter call check
|
||||
private Boolean autoGenerated;
|
||||
private Boolean autoTranslated;
|
||||
|
||||
/**
|
||||
* Create a new {@link Builder} instance with default values.
|
||||
@ -152,6 +154,18 @@ public final class SubtitlesStream extends Stream {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether the subtitles have been automatically translated
|
||||
* (i.e. by a machine like Google Translator) by the streaming service.
|
||||
* @param autoTranslated whether the subtitles have been automatically translated by the
|
||||
* streaming service
|
||||
* @return this {@link Builder} instance
|
||||
*/
|
||||
public Builder setAutoTranslated(final boolean autoTranslated) {
|
||||
this.autoTranslated = autoTranslated;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a {@link SubtitlesStream} using the builder's current values.
|
||||
*
|
||||
@ -196,13 +210,19 @@ public final class SubtitlesStream extends Stream {
|
||||
+ "with setIsAutoGenerated.");
|
||||
}
|
||||
|
||||
if (autoTranslated == null) {
|
||||
throw new IllegalStateException("The subtitles stream has been not set as an "
|
||||
+ "automatically translated subtitles stream or not. "
|
||||
+ "Please specify this information with setIsAutoTranslated.");
|
||||
}
|
||||
|
||||
if (id == null) {
|
||||
id = languageCode + (mediaFormat != null ? "." + mediaFormat.suffix
|
||||
: "");
|
||||
}
|
||||
|
||||
return new SubtitlesStream(id, content, isUrl, mediaFormat, deliveryMethod,
|
||||
languageCode, autoGenerated, manifestUrl);
|
||||
languageCode, autoGenerated, autoTranslated, manifestUrl);
|
||||
}
|
||||
}
|
||||
|
||||
@ -219,6 +239,7 @@ public final class SubtitlesStream extends Stream {
|
||||
* @param deliveryMethod the {@link DeliveryMethod} of the stream
|
||||
* @param languageCode the language code of the stream
|
||||
* @param autoGenerated whether the subtitles are auto-generated by the streaming service
|
||||
* @param autoTranslated whether the subtitles are auto-translated by the streaming service
|
||||
* @param manifestUrl the URL of the manifest this stream comes from (if applicable,
|
||||
* otherwise null)
|
||||
*/
|
||||
@ -230,6 +251,7 @@ public final class SubtitlesStream extends Stream {
|
||||
@Nonnull final DeliveryMethod deliveryMethod,
|
||||
@Nonnull final String languageCode,
|
||||
final boolean autoGenerated,
|
||||
final boolean autoTranslated,
|
||||
@Nullable final String manifestUrl) throws ParsingException {
|
||||
super(id, content, isUrl, mediaFormat, deliveryMethod, manifestUrl);
|
||||
this.locale = LocaleCompat.forLanguageTag(languageCode).orElseThrow(
|
||||
@ -238,6 +260,7 @@ public final class SubtitlesStream extends Stream {
|
||||
this.code = languageCode;
|
||||
this.format = mediaFormat;
|
||||
this.autoGenerated = autoGenerated;
|
||||
this.autoTranslated = autoTranslated;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -250,7 +273,7 @@ public final class SubtitlesStream extends Stream {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether if the subtitles are auto-generated.
|
||||
* Return whether the subtitles are auto-generated.
|
||||
* <p>
|
||||
* Some streaming services can generate subtitles for their contents, like YouTube.
|
||||
* </p>
|
||||
@ -261,6 +284,21 @@ public final class SubtitlesStream extends Stream {
|
||||
return autoGenerated;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the subtitles are translated automatically by a machine.
|
||||
*
|
||||
* <p>
|
||||
* Some streaming services provide automatically translated subtitles.
|
||||
* YouTube, for example, uses Google translator to generate translated subtitles.
|
||||
* Automatically translated subtitles might not coincide completely with the original text.
|
||||
* </p>
|
||||
*
|
||||
* @return {code true} if the subtitles are auto-translated, {@link false} otherwise
|
||||
*/
|
||||
public boolean isAutoTranslated() {
|
||||
return autoTranslated;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user