Skip to content

Commit f084cfe

Browse files
committed
Refactor frames extraction
1 parent a6c94c7 commit f084cfe

5 files changed

Lines changed: 140 additions & 145 deletions

File tree

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

Lines changed: 56 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1036,28 +1036,60 @@ public String getThumbnailUrl() throws ParsingException {
10361036
};
10371037
}
10381038

1039-
@Nullable
1040-
public StreamFrames getFrames() {
1041-
try {
1042-
final String script = doc.select("#player-api").first().siblingElements().select("script").html();
1043-
int p = script.indexOf("ytplayer.config");
1044-
if (p == -1) {
1045-
return null;
1046-
}
1047-
p = script.indexOf('{', p);
1048-
int e = script.indexOf("ytplayer.load", p);
1049-
if (e == -1) {
1050-
return null;
1051-
}
1052-
JsonObject jo = JsonParser.object().from(script.substring(p, e - 1));
1053-
final String resp = jo.getObject("args").getString("player_response");
1054-
jo = JsonParser.object().from(resp);
1055-
final String[] spec = jo.getObject("storyboards").getObject("playerStoryboardSpecRenderer").getString("spec").split("\\|");
1056-
final String url = spec[0];
1057-
final List<String> opts = Arrays.asList(spec).subList(1, spec.length);
1058-
return new StreamFrames(url, opts);
1059-
} catch (Exception e) {
1060-
return null;
1061-
}
1062-
}
1039+
@Nonnull
1040+
@Override
1041+
public List<Frameset> getFrames() throws ExtractionException {
1042+
try {
1043+
final String script = doc.select("#player-api").first().siblingElements().select("script").html();
1044+
int p = script.indexOf("ytplayer.config");
1045+
if (p == -1) {
1046+
return Collections.emptyList();
1047+
}
1048+
p = script.indexOf('{', p);
1049+
int e = script.indexOf("ytplayer.load", p);
1050+
if (e == -1) {
1051+
return Collections.emptyList();
1052+
}
1053+
JsonObject jo = JsonParser.object().from(script.substring(p, e - 1));
1054+
final String resp = jo.getObject("args").getString("player_response");
1055+
jo = JsonParser.object().from(resp);
1056+
final String[] spec = jo.getObject("storyboards").getObject("playerStoryboardSpecRenderer").getString("spec").split("\\|");
1057+
final String url = spec[0];
1058+
final ArrayList<Frameset> result = new ArrayList<>(spec.length - 1);
1059+
for (int i = 1; i < spec.length; ++i) {
1060+
final String[] parts = spec[i].split("#");
1061+
if (parts.length != 8) {
1062+
continue;
1063+
}
1064+
final int frameWidth = Integer.parseInt(parts[0]);
1065+
final int frameHeight = Integer.parseInt(parts[1]);
1066+
final int totalCount = Integer.parseInt(parts[2]);
1067+
final int framesPerPageX = Integer.parseInt(parts[3]);
1068+
final int framesPerPageY = Integer.parseInt(parts[4]);
1069+
final String baseUrl = url.replace("$L", String.valueOf(i - 1)).replace("$N", parts[6]) + "&sigh=" + parts[7];
1070+
final List<String> urls;
1071+
if (baseUrl.contains("$M")) {
1072+
final int totalPages = (int) Math.ceil(totalCount / (double) (framesPerPageX * framesPerPageY));
1073+
urls = new ArrayList<>(totalPages);
1074+
for (int j = 0; j < totalPages; j++) {
1075+
urls.add(baseUrl.replace("$M", String.valueOf(j)));
1076+
}
1077+
} else {
1078+
urls = Collections.singletonList(baseUrl);
1079+
}
1080+
result.add(new Frameset(
1081+
urls,
1082+
frameWidth,
1083+
frameHeight,
1084+
totalCount,
1085+
framesPerPageX,
1086+
framesPerPageY
1087+
));
1088+
}
1089+
result.trimToSize();
1090+
return result;
1091+
} catch (Exception e) {
1092+
throw new ExtractionException(e);
1093+
}
1094+
}
10631095
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
package org.schabi.newpipe.extractor.stream;
2+
3+
import javax.annotation.Nullable;
4+
import java.util.Collection;
5+
import java.util.List;
6+
7+
public final class Frameset {
8+
9+
private List<String> urls;
10+
private int frameWidth;
11+
private int frameHeight;
12+
private int totalCount;
13+
private int framesPerPageX;
14+
private int framesPerPageY;
15+
16+
public Frameset(List<String> urls, int frameWidth, int frameHeight, int totalCount, int framesPerPageX, int framesPerPageY) {
17+
this.urls = urls;
18+
this.totalCount = totalCount;
19+
this.frameWidth = frameWidth;
20+
this.frameHeight = frameHeight;
21+
this.framesPerPageX = framesPerPageX;
22+
this.framesPerPageY = framesPerPageY;
23+
}
24+
25+
public List<String> getUrls() {
26+
return urls;
27+
}
28+
29+
/**
30+
* @return total count of frames
31+
*/
32+
public int getTotalCount() {
33+
return totalCount;
34+
}
35+
36+
/**
37+
* @return maximum frames count by x
38+
*/
39+
public int getFramesPerPageX() {
40+
return framesPerPageX;
41+
}
42+
43+
/**
44+
* @return maximum frames count by y
45+
*/
46+
public int getFramesPerPageY() {
47+
return framesPerPageY;
48+
}
49+
50+
/**
51+
* @return width of a one frame, in pixels
52+
*/
53+
public int getFrameWidth() {
54+
return frameWidth;
55+
}
56+
57+
/**
58+
* @return height of a one frame, in pixels
59+
*/
60+
public int getFrameHeight() {
61+
return frameHeight;
62+
}
63+
}

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

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,10 @@
3030
import org.schabi.newpipe.extractor.utils.Parser;
3131

3232
import javax.annotation.Nonnull;
33+
import javax.annotation.Nullable;
3334
import java.io.IOException;
35+
import java.util.ArrayList;
36+
import java.util.Collections;
3437
import java.util.List;
3538

3639
/**
@@ -255,6 +258,15 @@ public StreamExtractor(StreamingService service, LinkHandler linkHandler, Locali
255258
*/
256259
public abstract StreamInfoItemsCollector getRelatedStreams() throws IOException, ExtractionException;
257260

261+
/**
262+
* Should return a list of frames
263+
* @return
264+
*/
265+
@Nonnull
266+
public List<Frameset> getFrames() throws IOException, ExtractionException {
267+
return Collections.emptyList();
268+
}
269+
258270
/**
259271
* Should analyse the webpage's document and extracts any error message there might be. (e.g. GEMA block)
260272
*

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

Lines changed: 0 additions & 113 deletions
This file was deleted.

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

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import org.junit.BeforeClass;
44
import org.junit.Test;
55
import org.schabi.newpipe.Downloader;
6+
import org.schabi.newpipe.extractor.ExtractorAsserts;
67
import org.schabi.newpipe.extractor.MediaFormat;
78
import org.schabi.newpipe.extractor.NewPipe;
89
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
@@ -13,6 +14,7 @@
1314
import org.schabi.newpipe.extractor.utils.Utils;
1415

1516
import java.io.IOException;
17+
import java.util.List;
1618

1719
import static org.junit.Assert.*;
1820
import static org.schabi.newpipe.extractor.ExtractorAsserts.assertIsSecureUrl;
@@ -244,15 +246,14 @@ public static void setUp() throws Exception {
244246
}
245247

246248
@Test
247-
public void testGetFrames() {
248-
final StreamFrames frames = extractor.getFrames();
249+
public void testGetFrames() throws ExtractionException {
250+
final List<Frameset> frames = extractor.getFrames();
249251
assertNotNull(frames);
250-
assertNotNull(frames.getDefaultVariant());
251-
for (int i=0;i<frames.getVariantsCount();i++) {
252-
final StreamFrames.Frameset frameset = frames.getVariant(i);
253-
final int pages = frameset.getTotalPages();
254-
final String url = pages == 0 ? frameset.getUrl() : frameset.getUrl(pages - 1);
255-
assertNotNull(url);
252+
assertFalse(frames.isEmpty());
253+
for (final Frameset f : frames) {
254+
for (final String url : f.getUrls()) {
255+
ExtractorAsserts.assertIsValidUrl(url);
256+
}
256257
}
257258
}
258259
}

0 commit comments

Comments
 (0)