diff options
-rw-r--r-- | README.md | 11 | ||||
-rw-r--r-- | rtv4d-dl.c | 177 | ||||
-rw-r--r-- | tcp.c | 2 |
3 files changed, 163 insertions, 27 deletions
@@ -9,7 +9,7 @@ namestitev prek upravitelja paketov `apt`. ``` wget https://sijanec.eu/pgp-key.txt -qO- | sudo apt-key add - -sudo apt-add-repository https://prog.sijanec.eu/ppa +sudo echo deb http://prog.sijanec.eu/ $(lsb_release -sc) main \>\> /etc/apt/sources.list sudo apt update sudo apt install rtv4d-dl ``` @@ -59,10 +59,14 @@ z uporabo programa se strinjate z naslednjimi stavki: * program se poveže na \*.rtvslo.si, spremenite izvorno kodo za drugo infrastrukturo * **živo**: za možne programe in razlago dolžine glej *dodatno o prenosu v živo* +* če RTV strežnik ne ponuja enotne .mp4 datoteke za oddajo ampak zgolj HLS, se + bo oddaja shranila kot kosi prenosa v živo (datoteka.mp4 => datoteka/....m3u8) + - take datoteke lahko kasneje združite z ukazom + `cat datoteka/*.ts | ffmpeg -i - -c:v copy -c:a copy datoteka.mp4` # trenutna izdaja programa: -* program je bil nazadnje ročno testiran 11. januarja 2021 in takrat je DELOVAL. -* različica: 0.1.1 +* program je bil nazadnje ročno testiran 29. januarja 2021 in takrat je DELOVAL. +* različica: 0.1.2 ## dnevnik sprememb: * 0.0.2 - 13. december 2020: sedaj pravilno naloži samo največjo kvaliteto, pred @@ -77,6 +81,7 @@ z uporabo programa se strinjate z naslednjimi stavki: izogne, ne bom več gradil okenskih datotek * 0.1.0 - 11. januar 2021: paket za debian/ubuntu * 0.1.1 - 11. januar 2021: standardizacija Makefile +* 0.1.2 - 29. januar 2021: dodano nalaganje geoblokiranih datotek prek HLS # o * program je spisan 100% v C programskem jeziku @@ -45,8 +45,9 @@ #define RTV_NAPISI(kaj, frmt, ...) /* pazi na format string RCE! */ \ do { if ( RTV_NAPISI_ ##kaj ) fprintf(stderr, \ "[" #kaj "] %s@%s:" NIZ(__LINE__) " " frmt "\n", \ - __func__, __FILE__, ##__VA_ARGS__ ); } while(0); -#define RTV_VER "0.1.1" + __func__, __FILE__, ##__VA_ARGS__ ); \ + fflush(stderr); } while(0); +#define RTV_VER "0.1.2" #define RTV_USER_AGENT "Mozilla/5.0 equivalent (rtv4d-dl " RTV_VER "; C " \ NIZ(__STDC_VERSION__) " GCC " __VERSION__ "; " __DATE__ " " __TIME__ "; " \ __FILE__ ":" NIZ(__LINE__) ")" @@ -111,7 +112,7 @@ if (strncmp(otr, str+RTV_JSON_i-(2+strlen(otr)), strlen(otr)) == 0) \ RTV_JSON_globina++; \ } \ - if ( (RTV_JSON_globina > 0 || otr == NULL) \ + if ( ( RTV_JSON_globina > 0 || otr == NULL) \ && strncmp(str+RTV_JSON_i, key, strlen(key)) == 0) { \ RTV_JSON_IZPOLNI(out, fmt, spl, RTV_JSON_VALUE(str, RTV_JSON_i, key)); \ break; \ @@ -359,6 +360,8 @@ int rtv_meta_izpolni(struct meta_oddaja * m) { FILE * odgstream; char * odg; size_t sizeloc; + size_t i; + char * c; RTV_JSON_INIT(); snprintf(m->get_meta_url, RTV_API_META_URL_SIZEOF, RTV_API_META_URL, m->id); snprintf(m->predvajalnik_url, RTV_PREDVAJALNIK_URL_SIZEOF, RTV_PREDVAJALNIK_URL, m->id); @@ -440,8 +443,44 @@ int rtv_meta_izpolni(struct meta_oddaja * m) { RTV_HTTPS_V_HTTP(m->posnetek_url); goto rtv_meta_izpolni_naselnajboljsistream; } + /* očitno še nismo našli ustreznega naslova, poskusimo hardcore */ + RTV_NAPISI(INFO, "nisem našel direktnega mp4 URLja, poskušam HLS."); + RTV_JSON(odg, sizeloc, "\"hls\"", m->posnetek_url, s, '"', + "addaptiveMedia"); /* addaptiveMedia je fuckery m3u8 fajlov */ + if (m->posnetek_url[0] == '\0') { + RTV_NAPISI(NAPAKA, "ni uspelo pridobiti HLS URLja."); + returnstatus = 1; + goto rtv_meta_izpolni_returncleanly; + } + /* na mojo srečo je tukaj sicer najboljši stream vedno prvi */ + rewind(odgstream); + fflush(odgstream); + returnstatus = http_get(m->posnetek_url, odgstream); + if (!RTV_HTTP_SUCCESS(returnstatus)) { + RTV_NAPISI(NAPAKA, "zahteva za HLS naslov je spodletela."); + goto rtv_meta_izpolni_returncleanly; + } else returnstatus = 0; + fflush(odgstream); + for (i = 0; i < sizeloc && odg[i] != '\0'; i++) { + if ((i == 0 && odg[i] != '#') + || (i != 0 && odg[i-1] == '\n' && odg[i] != '#')) { + c = strrchr(m->posnetek_url, '/'); + if (c == NULL) { + RTV_NAPISI(NAPAKA, "napaka na tej vrstici, kontaktiraj razvijalce"); + returnstatus = 1; + goto rtv_meta_izpolni_returncleanly; + } + if (m->posnetek_url_sizeof-1 < /* če ni dovolj prostora */ + ((c+(strchrnul(odg+i, '\n')-(odg+i)))-m->posnetek_url)) { + m->posnetek_url_sizeof = + ((c+(strchrnul(odg+i, '\n')-(odg+i)))-m->posnetek_url) + 25; + m->posnetek_url = realloc(m->posnetek_url, m->posnetek_url_sizeof); + } + strncpy(c+1, odg+i, strchrnul(odg+i, '\n')-(odg+i)); + break; + } + } rtv_meta_izpolni_naselnajboljsistream: - rtv_meta_izpolni_returncleanly: fclose(odgstream); free(odg); @@ -611,7 +650,86 @@ int rtv_zivo_izpolni(struct rtv_zivo_meta * m) { return returnstatus; #pragma GCC diagnostic pop } - +int rtv_prenesi_hls (char * url, char * datotecna_predpona) { + int returnstatus; + DIR * dir; + size_t max_kos_fn = strlen("seznam_predvajanja.m3u8"); + char * fn=malloc(sizeof(char)*(strlen(datotecna_predpona)+2+max_kos_fn)); + char * odg; + size_t sizeloc; + FILE * odgstream = open_memstream(&odg, &sizeloc); + size_t kosov = 0; + size_t i = 0; + size_t ti = 0; /* temp in temp intt */ + char ** k /* kosi */ = malloc(sizeof(char *)*1); + FILE * fd = NULL; + FILE * fd2 = NULL; + char * c; + returnstatus = http_get(url, odgstream); /* shranimo m3u8 */ + if (!RTV_HTTP_SUCCESS(returnstatus)) { + RTV_NAPISI(NAPAKA, "ni uspelo prenesti HLS datoteke"); + returnstatus = 1; + goto returncleanly; + } else returnstatus = 0; + fflush(odgstream); + dir = opendir(datotecna_predpona); + if (dir) { + closedir(dir); /* direktorij obstaja, hvala */ + } else if (errno == ENOENT) { + if (mkdir(datotecna_predpona, 0755) != 0) { + RTV_NAPISI(NAPAKA, "med izdelavo direktorija: %s", strerror(errno)); + } + } else { + RTV_NAPISI(NAPAKA, "med iskanjem direktorija: %s", + strerror(errno)); + returnstatus = 5; + goto returncleanly; + } + for (i = 0; i <= sizeloc && odg[i] != '\0'; i++) { + if (odg[i] == '\n') + odg[i] = '\0'; + if ((i == 0 && odg[i] != '#') + || (i != 0 && odg[i-1] == '\0' /* == '\n' */ && odg[i] != '#')) { + k = realloc(k, sizeof(char *)*i+2); + k[kosov++] = odg+i; + ti = strlen(odg+i); + if (ti > max_kos_fn) + max_kos_fn = ti; + } + } + sprintf(fn, "%s/seznam_predvajanja.m3u8", datotecna_predpona); + fd2 = fopen(fn, "w"); + fprintf(fd2, "# generiral rtv4d-dl\n"); + fn=realloc(fn,sizeof(char)*(strlen(datotecna_predpona)+1+1+max_kos_fn + +strlen(url))); + for (i = 0; i < kosov; i++) { + c = strchrnul(k[i], '?'); + c[0] = '\0'; + sprintf(fn, "%s/%05lu%s", datotecna_predpona, i, strchrnul(k[i], '.')); + fprintf(fd2, "%05lu%s\n", i, strchrnul(k[i], '.')); + if (c != NULL) + c[0] = '?'; + RTV_NAPISI(HROSC, "prenašam %lu. kos oddaje od %lu v datoteko %s", + i+1, kosov, fn); + fd = fopen(fn, "w"); + strcpy(fn, url); + strcpy(strrchr(fn, '/')+1, k[i]); /* c'mon, url mora imeti / */ + returnstatus = http_get(fn, fd); /* shranimo ts */ + if (!RTV_HTTP_SUCCESS(returnstatus)) { + RTV_NAPISI(NAPAKA, "ni uspelo prenesti TS datoteke"); + returnstatus = 1; + goto returncleanly; + } else returnstatus = 0; + fclose(fd); + } + fflush(fd2); + fclose(fd2); +returncleanly: + fclose(odgstream); + free(odg); + odg = NULL; + return returnstatus; +} int main (int argc, char ** argv) { if (argc < 1+1) { fprintf(stderr, "preberi README.md pred uporabo programa, saj vsebuje " @@ -667,25 +785,38 @@ int main (int argc, char ** argv) { returnstatus = 4; goto returncleanly; } - if (argc < 4) { - e = strrchr(m->posnetek_url, '.'); - snprintf(fn, 68, "%u%.4s", m->id, e); - fd = fopen(fn, "w"); - } else { - fd = fopen(argv[3], "w"); - } - if (fd == NULL) { - RTV_NAPISI(NAPAKA, "Ni uspelo odpreti datoteke za pisanje vanjo."); - returnstatus = 5; - goto returncleanly; - } - if (RTV_HTTP_SUCCESS(http_get(m->posnetek_url, fd))) { - fclose(fd); - RTV_NAPISI(INFO, "uspešno shranjeno."); + if (strstr(m->posnetek_url, ".m3u8") != NULL) { + if (argc < 4) + snprintf(fn, 68, "%u", m->id); + else + strncpy(fn, argv[3], 419); + e = strrchr(fn, '.'); + if (e != NULL) + e[0] = '\0'; + if (rtv_prenesi_hls(m->posnetek_url, fn) != 0) + RTV_NAPISI(NAPAKA, "nisem uspel narediti HLS prenosa."); + RTV_NAPISI(INFO, "uspešno prenesel oddajo v mapo po kosih."); } else { - fclose(fd); - RTV_NAPISI(NAPAKA, "Nekaj je spodletelo pri http_get()"); - returnstatus = 6; + if (argc < 4) { + e = strrchr(m->posnetek_url, '.'); + snprintf(fn, 68, "%u%.4s", m->id, e); + fd = fopen(fn, "w"); + } else { + fd = fopen(argv[3], "w"); + } + if (fd == NULL) { + RTV_NAPISI(NAPAKA, "Ni uspelo odpreti datoteke za pisanje vanjo."); + returnstatus = 5; + goto returncleanly; + } + if (RTV_HTTP_SUCCESS(http_get(m->posnetek_url, fd))) { + fclose(fd); + RTV_NAPISI(INFO, "uspešno shranjeno."); + } else { + fclose(fd); + RTV_NAPISI(NAPAKA, "Nekaj je spodletelo pri http_get()"); + returnstatus = 6; + } } break; case 'M': @@ -13,7 +13,7 @@ #include <string.h> #include <sys/time.h> #define ERR_INET_ADDR "0.9.9.0" -#define TCPC_READ_BUF 1048576 /* en megabajt */ +#define TCPC_READ_BUF 1024 /* en kilobajt */ #define TCPC_RESOLVE_RETRIES 12 union ip_conv { unsigned char c[4]; |