]> git.sur5r.net Git - minitube/blob - src/yt/ytjs/ytjsvideo.cpp
New upstream version 3.8
[minitube] / src / yt / ytjs / ytjsvideo.cpp
1 #include "ytjsvideo.h"
2
3 #include "js.h"
4 #include "videodefinition.h"
5 #include "yt3.h"
6
7 YTJSVideo::YTJSVideo(const QString &videoId, QObject *parent)
8     : QObject(parent), videoId(videoId), definitionCode(0) {}
9
10 void YTJSVideo::loadStreamUrl() {
11     if (loadingStreamUrl) return;
12     loadingStreamUrl = true;
13
14     JS::instance()
15             .callFunction(new JSResult(this), "videoInfo", {videoId})
16             .onJson([this](auto &doc) {
17                 auto obj = doc.object();
18
19                 QMap<int, QString> urlMap;
20                 const auto formats = obj["formats"].toArray();
21                 for (const auto &format : formats) {
22                     bool isDashMpd = format["isDashMPD"].toBool();
23                     if (isDashMpd) continue;
24                     int itag = format["itag"].toInt();
25                     QString url = format["url"].toString();
26                     // qDebug() << itag << url;
27                     urlMap.insert(itag, url);
28                 }
29                 if (urlMap.isEmpty()) {
30                     loadingStreamUrl = false;
31                     emit errorStreamUrl("No formats");
32                     return;
33                 }
34
35                 qDebug() << "available formats" << urlMap.keys();
36                 const VideoDefinition &definition = YT3::instance().maxVideoDefinition();
37                 const QVector<VideoDefinition> &definitions = VideoDefinition::getDefinitions();
38                 int previousIndex = std::max(definitions.indexOf(definition), 0);
39                 for (; previousIndex >= 0; previousIndex--) {
40                     const VideoDefinition &previousDefinition = definitions.at(previousIndex);
41                     qDebug() << "Testing format" << previousDefinition.getCode();
42                     if (urlMap.contains(previousDefinition.getCode())) {
43                         qDebug() << "Found format" << previousDefinition.getCode();
44
45                         QString url = urlMap.value(previousDefinition.getCode());
46                         definitionCode = previousDefinition.getCode();
47
48                         QString audioUrl;
49                         if (!previousDefinition.hasAudio()) {
50                             qDebug() << "Finding audio format";
51                             static const QVector<int> audioFormats({251, 171, 140});
52                             for (int audioFormat : audioFormats) {
53                                 qDebug() << "Trying audio format" << audioFormat;
54                                 auto i = urlMap.constFind(audioFormat);
55                                 if (i != urlMap.constEnd()) {
56                                     qDebug() << "Found audio format" << i.value();
57                                     audioUrl = i.value();
58                                     break;
59                                 }
60                             }
61                         }
62
63                         loadingStreamUrl = false;
64                         emit gotStreamUrl(url, audioUrl);
65                         return;
66                     }
67                 }
68
69                 loadingStreamUrl = false;
70                 emit errorStreamUrl(tr("Cannot get video stream for %1").arg(videoId));
71             })
72             .onError([this](auto &msg) {
73                 loadingStreamUrl = false;
74                 emit errorStreamUrl(msg);
75             });
76 }