Skip to content

Commit 6f3f608

Browse files
committed
Add support for extracting channel subscriber count in StreamInfo.
1 parent 69e18c8 commit 6f3f608

6 files changed

Lines changed: 53 additions & 0 deletions

File tree

extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeStreamExtractor.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
import java.time.format.DateTimeFormatter;
4646
import java.util.*;
4747

48+
import static org.schabi.newpipe.extractor.ListExtractor.ITEM_COUNT_UNKNOWN;
4849
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.*;
4950
import static org.schabi.newpipe.extractor.utils.Utils.EMPTY_STRING;
5051
import static org.schabi.newpipe.extractor.utils.Utils.UTF_8;
@@ -437,6 +438,20 @@ public String getUploaderAvatarUrl() throws ParsingException {
437438
return fixThumbnailUrl(url);
438439
}
439440

441+
@Override
442+
public long getUploaderSubscriberCount() throws ParsingException {
443+
final JsonObject videoOwnerRenderer = JsonUtils.getObject(videoSecondaryInfoRenderer, "owner.videoOwnerRenderer");
444+
if (videoOwnerRenderer.has("subscriberCountText")) {
445+
try {
446+
return Utils.mixedNumberWordToLong(getTextFromObject(videoOwnerRenderer.getObject("subscriberCountText")));
447+
} catch (final NumberFormatException e) {
448+
throw new ParsingException("Could not get subscriber count", e);
449+
}
450+
} else {
451+
return ITEM_COUNT_UNKNOWN;
452+
}
453+
}
454+
440455
@Nonnull
441456
@Override
442457
public String getDashMpdUrl() throws ParsingException {

extractor/src/main/java/org/schabi/newpipe/extractor/stream/StreamExtractor.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,17 @@ public boolean isUploaderVerified() throws ParsingException {
202202
return false;
203203
}
204204

205+
/**
206+
* The subscriber count of the uploader.
207+
* If the subscriber count is not implemented, or is unavailable, return <code>-1</code>.
208+
*
209+
* @return the subscriber count of the uploader or -1 if not available
210+
* @throws ParsingException
211+
*/
212+
public long getUploaderSubscriberCount() throws ParsingException {
213+
return -1;
214+
}
215+
205216
/**
206217
* The url to the image file/profile picture/avatar of the creator/uploader of the stream.
207218
* If the url is not available you can return an empty String.

extractor/src/main/java/org/schabi/newpipe/extractor/stream/StreamInfo.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,11 @@ private static StreamInfo extractOptionalData(StreamInfo streamInfo, StreamExtra
235235
} catch (Exception e) {
236236
streamInfo.addError(e);
237237
}
238+
try {
239+
streamInfo.setUploaderSubscriberCount(extractor.getUploaderSubscriberCount());
240+
} catch (Exception e) {
241+
streamInfo.addError(e);
242+
}
238243

239244
try {
240245
streamInfo.setSubChannelName(extractor.getSubChannelName());
@@ -367,6 +372,7 @@ private static StreamInfo extractOptionalData(StreamInfo streamInfo, StreamExtra
367372
private String uploaderUrl = "";
368373
private String uploaderAvatarUrl = "";
369374
private boolean uploaderVerified = false;
375+
private long uploaderSubscriberCount = -1;
370376

371377
private String subChannelName = "";
372378
private String subChannelUrl = "";
@@ -540,6 +546,14 @@ public void setUploaderVerified(final boolean uploaderVerified) {
540546
this.uploaderVerified = uploaderVerified;
541547
}
542548

549+
public long getUploaderSubscriberCount() {
550+
return uploaderSubscriberCount;
551+
}
552+
553+
public void setUploaderSubscriberCount(long uploaderSubscriberCount) {
554+
this.uploaderSubscriberCount = uploaderSubscriberCount;
555+
}
556+
543557
public String getSubChannelName() {
544558
return subChannelName;
545559
}

extractor/src/test/java/org/schabi/newpipe/extractor/services/BaseStreamExtractorTest.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ public interface BaseStreamExtractorTest extends BaseExtractorTest {
55
void testUploaderName() throws Exception;
66
void testUploaderUrl() throws Exception;
77
void testUploaderAvatarUrl() throws Exception;
8+
void testSubscriberCount() throws Exception;
89
void testSubChannelName() throws Exception;
910
void testSubChannelUrl() throws Exception;
1011
void testSubChannelAvatarUrl() throws Exception;

extractor/src/test/java/org/schabi/newpipe/extractor/services/DefaultStreamExtractorTest.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ public abstract class DefaultStreamExtractorTest extends DefaultExtractorTest<St
4545
public abstract String expectedUploaderName();
4646
public abstract String expectedUploaderUrl();
4747
public boolean expectedUploaderVerified() { return false; }
48+
public long expectedUploaderSubscriberCountAtLeast() { return -1; }
4849
public String expectedSubChannelName() { return ""; } // default: there is no subchannel
4950
public String expectedSubChannelUrl() { return ""; } // default: there is no subchannel
5051
public boolean expectedDescriptionIsEmpty() { return false; } // default: description is not empty
@@ -105,6 +106,12 @@ public void testUploaderVerified() throws Exception {
105106
assertEquals(expectedUploaderVerified(), extractor().isUploaderVerified());
106107
}
107108

109+
@Test
110+
@Override
111+
public void testSubscriberCount() throws Exception {
112+
assertGreaterOrEqual(expectedUploaderSubscriberCountAtLeast(), extractor().getUploaderSubscriberCount());
113+
}
114+
108115
@Test
109116
@Override
110117
public void testSubChannelName() throws Exception {

extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/stream/YoutubeStreamExtractorDefaultTest.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@ public static void setUp() throws Exception {
138138
@Override public StreamType expectedStreamType() { return StreamType.VIDEO_STREAM; }
139139
@Override public String expectedUploaderName() { return "PewDiePie"; }
140140
@Override public String expectedUploaderUrl() { return "https://www.youtube.com/channel/UC-lHJZR3Gqxm24_Vd_AJ5Yw"; }
141+
@Override public long expectedUploaderSubscriberCountAtLeast() { return 110_000_000; }
141142
@Override public List<String> expectedDescriptionContains() {
142143
return Arrays.asList("https://www.youtube.com/channel/UC7l23W7gFi4Uho6WSzckZRA",
143144
"https://www.handcraftpictures.com/");
@@ -182,6 +183,7 @@ public static void setUp() throws Exception {
182183
@Override public StreamType expectedStreamType() { return StreamType.VIDEO_STREAM; }
183184
@Override public String expectedUploaderName() { return "Unbox Therapy"; }
184185
@Override public String expectedUploaderUrl() { return "https://www.youtube.com/channel/UCsTcErHg8oDvUnTzoqsYeNw"; }
186+
@Override public long expectedUploaderSubscriberCountAtLeast() { return 18_000_000; }
185187
@Override public List<String> expectedDescriptionContains() {
186188
return Arrays.asList("https://www.youtube.com/watch?v=X7FLCHVXpsA&list=PL7u4lWXQ3wfI_7PgX0C-VTiwLeu0S4v34",
187189
"https://www.youtube.com/watch?v=Lqv6G0pDNnw&list=PL7u4lWXQ3wfI_7PgX0C-VTiwLeu0S4v34",
@@ -274,6 +276,7 @@ public static void setUp() throws Exception {
274276
@Override public StreamType expectedStreamType() { return StreamType.VIDEO_STREAM; }
275277
@Override public String expectedUploaderName() { return "tagesschau"; }
276278
@Override public String expectedUploaderUrl() { return "https://www.youtube.com/channel/UC5NOEUbkLheQcaaRldYW5GA"; }
279+
@Override public long expectedUploaderSubscriberCountAtLeast() { return 1_000_000; }
277280
@Override public boolean expectedUploaderVerified() { return true; }
278281
@Override public List<String> expectedDescriptionContains() {
279282
return Arrays.asList("Themen der Sendung", "07:15", "Wetter", "Sendung nachträglich bearbeitet");
@@ -336,6 +339,7 @@ public static void setUp() throws Exception {
336339
@Override public StreamType expectedStreamType() { return StreamType.VIDEO_STREAM; }
337340
@Override public String expectedUploaderName() { return "maiLab"; }
338341
@Override public String expectedUploaderUrl() { return "https://www.youtube.com/channel/UCyHDQ5C6z1NDmJ4g6SerW8g"; }
342+
@Override public long expectedUploaderSubscriberCountAtLeast() { return 1_400_000; }
339343
@Override public List<String> expectedDescriptionContains() {return Arrays.asList("Vitamin", "2:44", "Was ist Vitamin D?");}
340344
@Override public boolean expectedUploaderVerified() { return true; }
341345
@Override public long expectedLength() { return 1010; }
@@ -405,6 +409,7 @@ public static void setUp() throws Exception {
405409
@Override public StreamType expectedStreamType() { return StreamType.VIDEO_STREAM; }
406410
@Override public String expectedUploaderName() { return "Dinge Erklärt – Kurzgesagt"; }
407411
@Override public String expectedUploaderUrl() { return "https://www.youtube.com/channel/UCwRH985XgMYXQ6NxXDo8npw"; }
412+
@Override public long expectedUploaderSubscriberCountAtLeast() { return 1_500_000; }
408413
@Override public List<String> expectedDescriptionContains() { return Arrays.asList("Lasst uns abtauchen!", "Angebot von funk", "Dinge"); }
409414
@Override public long expectedLength() { return 631; }
410415
@Override public long expectedTimestamp() { return TIMESTAMP; }

0 commit comments

Comments
 (0)