3 #include "videodefinition.h"
7 YTJSVideo::YTJSVideo(const QString &videoId, QObject *parent)
8 : QObject(parent), videoId(videoId), definitionCode(0) {}
10 void YTJSVideo::loadStreamUrl() {
11 auto &ytjs = YTJS::instance();
12 if (!ytjs.isInitialized()) {
13 QTimer::singleShot(500, this, [this] { loadStreamUrl(); });
16 auto &engine = ytjs.getEngine();
18 if (loadingStreamUrl) return;
19 loadingStreamUrl = true;
21 auto function = engine.evaluate("videoInfo");
22 if (!function.isCallable()) {
23 qWarning() << function.toString() << " is not callable";
24 loadingStreamUrl = false;
25 emit errorStreamUrl(function.toString());
29 auto handler = new ResultHandler;
30 connect(handler, &ResultHandler::error, this, &YTJSVideo::errorStreamUrl);
31 connect(handler, &ResultHandler::data, this, [this](const QJsonDocument &doc) {
32 auto obj = doc.object();
34 QMap<int, QString> urlMap;
35 const auto formats = obj["formats"].toArray();
36 for (const auto &format : formats) {
37 bool isDashMpd = format["isDashMPD"].toBool();
38 if (isDashMpd) continue;
39 int itag = format["itag"].toInt();
40 QString url = format["url"].toString();
41 // qDebug() << itag << url;
42 urlMap.insert(itag, url);
44 if (urlMap.isEmpty()) {
45 loadingStreamUrl = false;
46 emit errorStreamUrl("No formats");
50 qDebug() << "available formats" << urlMap.keys();
51 const VideoDefinition &definition = YT3::instance().maxVideoDefinition();
52 const QVector<VideoDefinition> &definitions = VideoDefinition::getDefinitions();
53 int previousIndex = std::max(definitions.indexOf(definition), 0);
54 for (; previousIndex >= 0; previousIndex--) {
55 const VideoDefinition &previousDefinition = definitions.at(previousIndex);
56 qDebug() << "Testing format" << previousDefinition.getCode();
57 if (urlMap.contains(previousDefinition.getCode())) {
58 qDebug() << "Found format" << previousDefinition.getCode();
60 QString url = urlMap.value(previousDefinition.getCode());
61 definitionCode = previousDefinition.getCode();
64 if (!previousDefinition.hasAudio()) {
65 qDebug() << "Finding audio format";
66 static const QVector<int> audioFormats({251, 171, 140});
67 for (int audioFormat : audioFormats) {
68 qDebug() << "Trying audio format" << audioFormat;
69 auto i = urlMap.constFind(audioFormat);
70 if (i != urlMap.constEnd()) {
71 qDebug() << "Found audio format" << i.value();
78 loadingStreamUrl = false;
79 emit gotStreamUrl(url, audioUrl);
84 loadingStreamUrl = false;
85 emit errorStreamUrl(tr("Cannot get video stream for %1").arg(videoId));
87 QJSValue h = engine.newQObject(handler);
88 auto value = function.call({h, videoId});
89 ytjs.checkError(value);