Skip to content

Commit

Permalink
[YouTube] Extract the audioChannels and the approxDurationMs values
Browse files Browse the repository at this point in the history
The first is only returned for audio streams, the second only for progressive streams.
These values are stored in the ItagItem class. Some default constants have been also added.
  • Loading branch information
AudricV committed Aug 19, 2021
1 parent a138daf commit b29f53c
Show file tree
Hide file tree
Showing 3 changed files with 109 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,8 @@ public static ItagItem getItag(final int itagId) throws ParsingException {
public static final int SAMPLE_RATE_UNKNOWN = -1;
public static final int FPS_UNKNOWN = -1;
public static final int TARGET_DURATION_SEC_UNKNOWN = -1;
public static final int APPROX_DURATION_MS_UNKNOWN = -1;
public static final int AUDIO_CHANNELS_NOT_APPLICABLE_OR_UNKNOWN = -1;

/*//////////////////////////////////////////////////////////////////////////
// Constructors and misc
Expand Down Expand Up @@ -174,6 +176,7 @@ public MediaFormat getMediaFormat() {
// Audio fields
public int avgBitrate = AVERAGE_BITRATE_UNKNOWN;
private int sampleRate = SAMPLE_RATE_UNKNOWN;
private int audioChannels = AUDIO_CHANNELS_NOT_APPLICABLE_OR_UNKNOWN;

// Video fields
public String resolutionString;
Expand All @@ -190,6 +193,7 @@ public MediaFormat getMediaFormat() {
private String quality;
private String codec;
private int targetDurationSec = TARGET_DURATION_SEC_UNKNOWN;
private int approxDurationMs = APPROX_DURATION_MS_UNKNOWN;

public int getBitrate() {
return bitrate;
Expand Down Expand Up @@ -263,6 +267,59 @@ public void setCodec(final String codec) {
this.codec = codec;
}

/**
* Get the sample rate.
* <p>
* It is only known for audio streams, so {@link #SAMPLE_RATE_UNKNOWN} is returned for video
* streams or if the sample rate is unknown.
* </p>
*
* @return the sample rate or {@link #SAMPLE_RATE_UNKNOWN}
*/
public int getSampleRate() {
return sampleRate;
}

/**
* Set the sample rate.
* <p>
* It is only known for audio streams, so {@link #SAMPLE_RATE_UNKNOWN} is set for video
* streams or if the sample rate value is less than or equal to 0.
* </p>
*/
public void setSampleRate(final int sampleRate) {
if (sampleRate > 0) {
this.sampleRate = sampleRate;
}
}

/**
* Get the number of audio channels.
* <p>
* It is only known for audio streams, so {@link #AUDIO_CHANNELS_NOT_APPLICABLE_OR_UNKNOWN} is
* returned for video streams or if it is unknown.
* </p>
*
* @return the number of audio channels or {@link #AUDIO_CHANNELS_NOT_APPLICABLE_OR_UNKNOWN}
*/
public int getAudioChannels() {
return audioChannels;
}

/**
* Set the number of audio channels.
* <p>
* It is only known for audio streams, so {@link #AUDIO_CHANNELS_NOT_APPLICABLE_OR_UNKNOWN} is
* set for video streams or if the {@code audioChannels} value is less than or equal to 0.
* </p>
* @param audioChannels the number of audio channels
*/
public void setAudioChannels(final int audioChannels) {
if (audioChannels > 0) {
this.audioChannels = audioChannels;
}
}

/**
* Get the {@code targetDurationSec} value.
* <p>
Expand All @@ -271,7 +328,7 @@ public void setCodec(final String codec) {
* videos, so {@link #TARGET_DURATION_SEC_UNKNOWN} is returned for video streams.
* </p>
*
* @return the targetDurationSec value or {@link #TARGET_DURATION_SEC_UNKNOWN}
* @return the {@code targetDurationSec} value or {@link #TARGET_DURATION_SEC_UNKNOWN}
*/
public int getTargetDurationSec() {
return targetDurationSec;
Expand All @@ -285,7 +342,6 @@ public int getTargetDurationSec() {
* videos, so {@link #TARGET_DURATION_SEC_UNKNOWN} will be set for video streams or if this
* value is less than or equal to 0.
* </p>
*
*/
public void setTargetDurationSec(final int targetDurationSec) {
if (targetDurationSec > 0) {
Expand All @@ -294,28 +350,28 @@ public void setTargetDurationSec(final int targetDurationSec) {
}

/**
* Get the sample rate.
* Get the {@code approxDurationMs} value.
* <p>
* It is only known for audio streams, so {@link #SAMPLE_RATE_UNKNOWN} is returned for video
* streams or if the sample rate is unknown.
* It is only known for DASH progressive streams, so {@link #APPROX_DURATION_MS_UNKNOWN} is
* returned for other stream types or if this value is less than or equal to 0.
* </p>
*
* @return the sample rate or {@link #SAMPLE_RATE_UNKNOWN}
* @return the {@code approxDurationMs} value or {@link #APPROX_DURATION_MS_UNKNOWN}
*/
public int getSampleRate() {
return sampleRate;
public int getApproxDurationMs() {
return approxDurationMs;
}

/**
* Set the sample rate.
* Set the {@code approxDurationMs} value.
* <p>
* It is only known for audio streams, so {@link #SAMPLE_RATE_UNKNOWN} is set for video
* streams or if the sample rate value is less than or equal to 0.
* It is only known for DASH progressive streams, so {@link #APPROX_DURATION_MS_UNKNOWN} is set
* for other stream types or if this value is less than or equal to 0.
* </p>
*/
public void setSampleRate(final int sampleRate) {
if (sampleRate > 0) {
this.sampleRate = sampleRate;
public void setApproxDurationMs(final int approxDurationMs) {
if (approxDurationMs > 0) {
this.approxDurationMs = approxDurationMs;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,9 @@ public static String createDashManifestFromOtfStreamingUrl(
generateAdaptationSetElement(document, itagItem.getMediaFormat().mimeType);
generateRoleElement(document);
generateRepresentationElement(document, itagItem);
if (itagItem.itagType == ItagItem.ItagType.AUDIO) {
generateAudioChannelConfigurationElement(document, itagItem);
}
generateSegmentTemplateElement(document, otfBaseStreamingUrl, false);
generateSegmentTimelineElement(document);
collectSegmentsData(segmentDuration);
Expand Down Expand Up @@ -165,11 +168,15 @@ public static String createDashManifestFromPostLiveStreamDvrStreamingUrl(
"Unable to generate the DASH manifest: could not get the number of segments");
}

final Document document = generateDocumentAndMpdElement(new String[] {streamDuration}, true);
final Document document = generateDocumentAndMpdElement(new String[] {streamDuration},
true);
generatePeriodElement(document);
generateAdaptationSetElement(document, itagItem.getMediaFormat().mimeType);
generateRoleElement(document);
generateRepresentationElement(document, itagItem);
if (itagItem.itagType == ItagItem.ItagType.AUDIO) {
generateAudioChannelConfigurationElement(document, itagItem);
}
generateSegmentTemplateElement(document, postLiveStreamDvrStreamingUrl, true);
generateSegmentTimelineElement(document);
generateSegmentElementsForPostLiveDvrStreams(document, targetDurationSec, segmentCount);
Expand Down Expand Up @@ -491,6 +498,36 @@ private static void generateRepresentationElement(@Nonnull final Document docume
}
}

private static void generateAudioChannelConfigurationElement(
@Nonnull final Document document,
@Nonnull final ItagItem itagItem) throws YoutubeDashManifestCreationException {
try {
final Element representationElement = (Element) document.getElementsByTagName(
"Representation").item(0);
final Element audioChannelConfigurationElement = document.createElement(
"AudioChannelConfiguration");

final Attr schemeIdUriAttribute = document.createAttribute("schemeIdUri");
schemeIdUriAttribute.setValue(
"urn:mpeg:dash:23003:3:audio_channel_configuration:2011");
audioChannelConfigurationElement.setAttributeNode(schemeIdUriAttribute);

final Attr valueAttribute = document.createAttribute("value");
final int audioChannels = itagItem.getAudioChannels();
if (audioChannels <= 0) {
throw new YoutubeDashManifestCreationException(
"Could not generate the DASH manifest: the audioChannels value is less than or equal to 0 (" + audioChannels + ")");
}
valueAttribute.setValue(String.valueOf(itagItem.getAudioChannels()));
audioChannelConfigurationElement.setAttributeNode(valueAttribute);

representationElement.appendChild(audioChannelConfigurationElement);
} catch (final DOMException e) {
throw new YoutubeDashManifestCreationException(
"Could not generate or append to the document the AudioChannelConfiguration element of the DASH manifest", e);
}
}

private static void generateSegmentTemplateElement(@Nonnull final Document document,
@Nonnull final String baseUrl,
final boolean isPostLiveDvr)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1257,6 +1257,7 @@ private List<ItagInfo> getStreamsFromStreamingDataKey(
if (itagType == ItagItem.ItagType.AUDIO) {
itagItem.setSampleRate(Integer.parseInt(formatData.getString(
"audioSampleRate")));
itagItem.setAudioChannels(formatData.getInt("audioChannels"));
}
final ItagInfo itagInfo = new ItagInfo(streamUrl, itagItem);

Expand Down

0 comments on commit b29f53c

Please sign in to comment.