mirror of
https://github.com/tuxbox-neutrino/neutrino.git
synced 2025-09-01 09:51:22 +02:00
ytparser: adjust to API changes (#12)
YouTube now enforces the HTML5 API for get_video_info, which provides the stream info in a JSON object.
This commit is contained in:
@@ -424,7 +424,6 @@ bool cYTFeedParser::supportedFormat(int fmt)
|
|||||||
bool cYTFeedParser::decodeVideoInfo(std::string &answer, cYTVideoInfo &vinfo)
|
bool cYTFeedParser::decodeVideoInfo(std::string &answer, cYTVideoInfo &vinfo)
|
||||||
{
|
{
|
||||||
bool ret = false;
|
bool ret = false;
|
||||||
decodeUrl(answer);
|
|
||||||
#if 0
|
#if 0
|
||||||
std::string infofile = thumbnail_dir;
|
std::string infofile = thumbnail_dir;
|
||||||
infofile += "/";
|
infofile += "/";
|
||||||
@@ -432,59 +431,79 @@ bool cYTFeedParser::decodeVideoInfo(std::string &answer, cYTVideoInfo &vinfo)
|
|||||||
infofile += ".txt";
|
infofile += ".txt";
|
||||||
saveToFile(infofile.c_str(), answer);
|
saveToFile(infofile.c_str(), answer);
|
||||||
#endif
|
#endif
|
||||||
if(answer.find("token=") == std::string::npos)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
//FIXME check expire
|
//FIXME check expire
|
||||||
std::vector<std::string> ulist;
|
std::vector<std::string> ulist;
|
||||||
std::string::size_type fmt = answer.find("url_encoded_fmt_stream_map=");
|
|
||||||
if (fmt != std::string::npos) {
|
|
||||||
fmt = answer.find("=", fmt);
|
|
||||||
splitString(answer, ",", ulist, fmt+1);
|
|
||||||
for (unsigned i = 0; i < ulist.size(); i++) {
|
|
||||||
#if 0 // to decode all params
|
|
||||||
decodeUrl(ulist[i]);
|
|
||||||
printf("URL: %s\n", ulist[i].c_str());
|
|
||||||
#endif
|
|
||||||
std::map<std::string,std::string> smap;
|
|
||||||
std::vector<std::string> uparams;
|
|
||||||
splitString(ulist[i], "&", uparams);
|
|
||||||
if (uparams.size() < 3)
|
|
||||||
continue;
|
|
||||||
for (unsigned j = 0; j < uparams.size(); j++) {
|
|
||||||
decodeUrl(uparams[j]);
|
|
||||||
#ifdef DEBUG_PARSER
|
|
||||||
printf(" param: %s\n", uparams[j].c_str());
|
|
||||||
#endif
|
|
||||||
splitString(uparams[j], "=", smap);
|
|
||||||
}
|
|
||||||
#ifdef DEBUG_PARSER
|
|
||||||
printf("=========================================================\n");
|
|
||||||
#endif
|
|
||||||
cYTVideoUrl yurl;
|
|
||||||
yurl.url = smap["url"];
|
|
||||||
std::size_t sig = std::string::npos;
|
|
||||||
std::string::size_type ptr = smap["url"].find("signature=");
|
|
||||||
if (ptr != std::string::npos)
|
|
||||||
{
|
|
||||||
ptr = smap["url"].find("=", ptr);
|
|
||||||
smap["url"].erase(0,ptr+1);
|
|
||||||
|
|
||||||
if((ptr = smap["url"].find("&")) != std::string::npos)
|
// Extract player_response
|
||||||
yurl.sig = smap["url"].substr(0,ptr);
|
std::string::size_type player_resp_start = answer.find("player_response=");
|
||||||
}else{
|
if (player_resp_start == std::string::npos) {
|
||||||
sig = smap["url"].find("&sig=");
|
printf("player_response not found\n");
|
||||||
}
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
int id = atoi(smap["itag"].c_str());
|
player_resp_start = answer.find("=", player_resp_start) + 1;
|
||||||
if (supportedFormat(id) && !yurl.url.empty() && (!yurl.sig.empty() || (sig != std::string::npos))) {
|
std::string::size_type player_resp_end = answer.find("&", player_resp_start);
|
||||||
yurl.quality = smap["quality"];
|
if (player_resp_end == std::string::npos) {
|
||||||
yurl.type = smap["type"];
|
player_resp_end = answer.length();
|
||||||
vinfo.formats.insert(yt_urlmap_pair_t(id, yurl));
|
}
|
||||||
ret = true;
|
std::string player_response = answer.substr(player_resp_start, player_resp_end - player_resp_start);
|
||||||
}
|
decodeUrl(player_response);
|
||||||
|
|
||||||
|
// Load player_response as json
|
||||||
|
Json::Value root;
|
||||||
|
if (!parseJsonFromString(player_response, &root, NULL)) {
|
||||||
|
printf("Decoding player_response failed\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Json::Value streamingData = root["streamingData"];
|
||||||
|
if (!streamingData) {
|
||||||
|
printf("streamingData element not present\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Json::Value formats = streamingData["formats"];
|
||||||
|
if (!formats) {
|
||||||
|
printf("formats element not present\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto it = formats.begin(); it != formats.end(); ++it) {
|
||||||
|
const Json::Value format = *it;
|
||||||
|
|
||||||
|
int id = format["itag"].asInt();
|
||||||
|
std::string quality = format["quality"].asString();
|
||||||
|
std::string url;
|
||||||
|
|
||||||
|
if (!format["url"].empty()) {
|
||||||
|
url = format["url"].asString();
|
||||||
|
} else if (!format["cipher"].empty()) {
|
||||||
|
// FIXME add support for cipher (is it still used or was it replaced by signatureCipher?)
|
||||||
|
printf("cipher unsupported: %s\n", format["cipher"].asCString());
|
||||||
|
continue;
|
||||||
|
} else if (!format["signatureCipher"].empty()) {
|
||||||
|
// FIXME add support for signatureCipher
|
||||||
|
printf("signatureCipher unsupported: %s\n", format["signatureCipher"].asCString());
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
printf("Unable to find url\n");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
#ifdef DEBUG_PARSER
|
||||||
|
printf("%d: %s - %s\n", id, quality.c_str(), url.c_str());
|
||||||
|
#endif
|
||||||
|
|
||||||
|
cYTVideoUrl yurl;
|
||||||
|
if (supportedFormat(id) && !url.empty()) {
|
||||||
|
yurl.quality = quality;
|
||||||
|
yurl.url = url;
|
||||||
|
yurl.type = format["mimeType"].asString();
|
||||||
|
vinfo.formats.insert(yt_urlmap_pair_t(id, yurl));
|
||||||
|
ret = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -592,7 +611,7 @@ bool cYTFeedParser::ParseVideoInfo(cYTVideoInfo &vinfo, CURL *_curl_handle)
|
|||||||
std::string vurl = "https://www.youtube.com/get_video_info?video_id=";
|
std::string vurl = "https://www.youtube.com/get_video_info?video_id=";
|
||||||
vurl += vinfo.id;
|
vurl += vinfo.id;
|
||||||
vurl += estr[i];
|
vurl += estr[i];
|
||||||
vurl += "&ps=default&eurl=&gl=US&hl=en";
|
vurl += "&ps=default&eurl=&gl=US&hl=en&html5=1";
|
||||||
printf("cYTFeedParser::ParseVideoInfo: get [%s]\n", vurl.c_str());
|
printf("cYTFeedParser::ParseVideoInfo: get [%s]\n", vurl.c_str());
|
||||||
std::string answer;
|
std::string answer;
|
||||||
if (!getUrl(vurl, answer, _curl_handle))
|
if (!getUrl(vurl, answer, _curl_handle))
|
||||||
|
Reference in New Issue
Block a user