summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAndrew Opalach <andrew@akon.city> 2023-11-11 17:51:49 -0500
committerAndrew Opalach <andrew@akon.city> 2023-11-11 17:51:49 -0500
commit7e5043a2505efa383ae372662fa4849051cd9799 (patch)
treee7736218b7ab323579a440f24d899ed00beb9f73 /src
parent113eb3b481417364f84350e90be252355d807f06 (diff)
downloadcamu-7e5043a2505efa383ae372662fa4849051cd9799.tar.gz
camu-7e5043a2505efa383ae372662fa4849051cd9799.tar.bz2
camu-7e5043a2505efa383ae372662fa4849051cd9799.zip
Improve basic cmv usage
- Make cap more robust - Disable ECHO in the TUI - Improve youtube playback url selection - Some cleanup Signed-off-by: Andrew Opalach <andrew@akon.city>
Diffstat (limited to 'src')
-rw-r--r--src/buffer/audio.c14
-rw-r--r--src/fruits/cap/cap.c87
-rw-r--r--src/fruits/cap/cap.h7
-rw-r--r--src/fruits/cmv/cmv2.c13
-rw-r--r--src/fruits/cmv/tui.c14
-rw-r--r--src/fruits/cmv/tui.h5
-rw-r--r--src/libclient/meson.build2
-rw-r--r--src/libsink/sink.c44
-rw-r--r--src/libsink/sink.h1
-rw-r--r--src/shoki/py/providers/twitter.py3
-rw-r--r--src/shoki/py/providers/youtube.py29
11 files changed, 150 insertions, 69 deletions
diff --git a/src/buffer/audio.c b/src/buffer/audio.c
index 34d3c65..939b98a 100644
--- a/src/buffer/audio.c
+++ b/src/buffer/audio.c
@@ -73,8 +73,8 @@ bool camu_audio_buffer_init(struct camu_audio_buffer *buf, struct camu_clock *cl
buf->clock = clock;
buf->pts = camu_mixer_get_latency(buf->mixer);
buf->buffered = false;
- buf->pause = PAUSE_PRE;
- //buf->pause = PAUSE_IGNORE_DESYNC;
+ //buf->pause = PAUSE_PRE;
+ buf->pause = PAUSE_IGNORE_DESYNC;
#ifdef CAMU_AUDIO_BUFFER_FADE
buf->fade_period = 0;
buf->fade_offset = 0;
@@ -248,6 +248,8 @@ static void handle_fade(struct camu_audio_buffer *buf, u8 *data, size_t size, bo
}
#endif
+#define NOT_UNPAUSED(pause) (pause != PAUSE_UNPAUSED && pause != PAUSE_PRE && pause != PAUSE_IGNORE_DESYNC)
+
size_t camu_audio_buffer_read(struct camu_audio_buffer *buf, u8 *data, size_t req)
{
f64 pts = camu_clock_get_pts(buf->clock);
@@ -260,7 +262,7 @@ size_t camu_audio_buffer_read(struct camu_audio_buffer *buf, u8 *data, size_t re
buf->pause = PAUSE_FADING;
} else if (buf->fade_period == 0) {
al_memset(data, 0, req);
- if (buf->pause != PAUSE_UNPAUSED && buf->pause != PAUSE_PRE) {
+ if (NOT_UNPAUSED(buf->pause)) {
buf->pause = PAUSE_UNPAUSED;
buf->callback(buf->userdata, CAMU_BUFFER_PAUSED);
}
@@ -273,7 +275,7 @@ size_t camu_audio_buffer_read(struct camu_audio_buffer *buf, u8 *data, size_t re
buf->pause = PAUSE_PLAYING;
#else
al_memset(data, 0, req);
- if (buf->pause != PAUSE_UNPAUSED && buf->pause != PAUSE_PRE) {
+ if (NOT_UNPAUSED(buf->pause)) {
buf->pause = PAUSE_UNPAUSED;
buf->callback(buf->userdata, CAMU_BUFFER_PAUSED);
}
@@ -315,12 +317,12 @@ size_t camu_audio_buffer_read(struct camu_audio_buffer *buf, u8 *data, size_t re
if (flow == FLUSHED) {
signal = size;
al_atomic_u8_store(&buf->flow, SIGNALED, AL_ATOMIC_RELAXED);
- al_log_debug("audio_buffer", "Flushed (signal: %li).", signal);
+ al_log_debug("audio_buffer", "Flushed (signal: %zu).", signal);
buf->callback(buf->userdata, CAMU_BUFFER_EOF);
} else {
al_memset(data + size, 0, req - size);
if (flow == FLOWING) {
- al_log_warn("audio_buffer", "Underrun (req: %i, have: %i).", req, size);
+ al_log_warn("audio_buffer", "Underrun (req: %zu, have: %zu).", req, size);
}
}
req = size;
diff --git a/src/fruits/cap/cap.c b/src/fruits/cap/cap.c
index 2f60cb4..e1d9e13 100644
--- a/src/fruits/cap/cap.c
+++ b/src/fruits/cap/cap.c
@@ -36,28 +36,25 @@ static struct cch_entry *entry_for_unique_id(str *unique_id)
#if CAP_USE_PYTHON
struct sho_search s;
sho_search_init(&s);
+ str query;
+ al_str_from(&query, "");
if (al_str_cmp(unique_id, al_str_c("https://twitter.com"), 0, 19) == 0 ||
al_str_cmp(unique_id, al_str_c("https://x.com"), 0, 13) == 0) {
- str query;
- al_str_from(&query, "tweet:");
+ al_str_cat(&query, al_str_c("tweet:"));
al_str_cat(&query, unique_id);
if (!sho_search_more_results(&s, al_str_c("twitter"), &query)) {
}
- al_str_free(&query);
} else {
- str query;
if (is_search) {
- //al_str_from(&query, "\"");
- al_str_from(&query, "");
al_str_cat(&query, al_str_substr(unique_id, 1, unique_id->len));
- //al_str_cat(&query, al_str_c("\""));
} else {
- al_str_from(&query, "link:");
+ al_str_cat(&query, al_str_c("link:"));
al_str_cat(&query, unique_id);
}
if (!sho_search_more_results(&s, al_str_c("youtube"), &query)) {
}
}
+ al_str_free(&query);
entry = NULL;
struct sho_result_page *page;
al_array_foreach_ptr(s.result.pages, k, page) {
@@ -77,7 +74,7 @@ static struct cch_entry *entry_for_unique_id(str *unique_id)
#else
if (!is_search) entry = cch_handler_http_create(unique_id);
#endif
- entry->handler->maybe_spawn_worker(entry->handler, 0);
+ if (entry) entry->handler->maybe_spawn_worker(entry->handler, 0);
} else // {
#endif
entry = cch_handler_file_create(unique_id);
@@ -87,10 +84,11 @@ static struct cch_entry *entry_for_unique_id(str *unique_id)
static bool buffer_entry(struct cap_runner *cap, struct cap_list *list, struct cap_list_entry *entry)
{
+ if (entry->errored) return false;
if (entry->buffer_requested) return true;
- struct cch_entry *centry = entry_for_unique_id(&entry->unique_id);
- if (!centry) return false;
- if (!cap->callback(cap->userdata, CAP_BUFFER, &list->name, &entry->unique_id, centry)) {
+ entry->entry = entry_for_unique_id(&entry->unique_id);
+ if (!entry->entry) return false;
+ if (!cap->callback(cap->userdata, CAP_BUFFER, &list->name, &entry->unique_id, entry->entry)) {
entry->errored = true;
return false;
}
@@ -102,7 +100,7 @@ static void maybe_cleanup_entries(struct cap_runner *cap, struct cap_list *list)
{
struct cap_list_entry *entry;
al_array_foreach_ptr(list->entries, i, entry) {
- if (entry->buffer_requested && abs((s32)i - list->current) >= 3) {
+ if (entry->buffer_requested && abs(list->current - (s32)i) >= 3) {
cap->callback(cap->userdata, CAP_UNLOAD, &list->name, &entry->unique_id, NULL);
entry->buffer_requested = false;
}
@@ -111,28 +109,34 @@ static void maybe_cleanup_entries(struct cap_runner *cap, struct cap_list *list)
static bool list_skip_internal(struct cap_runner *cap, struct cap_list *list, s32 n);
-static void list_pump_internal(struct cap_runner *cap, struct cap_list *list)
+static void list_pump_internal(struct cap_runner *cap, struct cap_list *list, bool buffer)
{
s32 size = (s32)list->entries.size;
if (size <= list->current) return;
+ if (buffer) list->buffer = true;
if (list->set != list->current) {
struct cap_list_entry *entry = &al_array_at(list->entries, list->current);
+ if (list->swap && !entry->buffer_requested) {
+ list->swap = false;
+ return;
+ }
if (!buffer_entry(cap, list, entry)) {
- list_skip_internal(cap, list, 1);
+ list_skip_internal(cap, list, list->forward ? 1 : -1);
return;
}
+ cap->callback(cap->userdata, list->swap ? CAP_SWAP : CAP_SET, &list->name, &entry->unique_id, NULL);
list->set = list->current;
- if (list->swap && entry->buffer_requested) {
- cap->callback(cap->userdata, CAP_SWAP, &list->name, &entry->unique_id, NULL);
- } else {
- cap->callback(cap->userdata, CAP_SET, &list->name, &entry->unique_id, NULL);
- }
- }
- if (list->current + 1 < size) {
- buffer_entry(cap, list, &al_array_at(list->entries, list->current + 1));
}
- if (list->current - 1 >= 0) {
- buffer_entry(cap, list, &al_array_at(list->entries, list->current - 1));
+ if (list->buffer) {
+ for (s32 i = 1; i <= 2; i++) {
+ if (list->current + i < size) {
+ buffer_entry(cap, list, &al_array_at(list->entries, list->current + i));
+ list->buffer = false;
+ }
+ if (list->current - i >= 0) {
+ buffer_entry(cap, list, &al_array_at(list->entries, list->current - i));
+ }
+ }
}
maybe_cleanup_entries(cap, list);
}
@@ -144,7 +148,8 @@ bool list_skip_internal(struct cap_runner *cap, struct cap_list *list, s32 n)
return false;
}
list->current += n;
- list_pump_internal(cap, list);
+ list->forward = n >= 0;
+ list_pump_internal(cap, list, false);
return true;
}
@@ -153,9 +158,12 @@ void cap_make_list(struct cap_runner *cap, str *name)
struct cap_list list;
al_str_clone(&list.name, name);
list.current = 0;
+ list.forward = true;
list.set = -1;
list.idle = false;
+ list.buffer = false;
list.swap = false;
+ aki_mutex_init(&list.mutex);
al_array_init(list.entries);
al_array_push(cap->lists, list);
}
@@ -164,39 +172,51 @@ void cap_list_add(struct cap_runner *cap, str *name, str *unique_id)
{
struct cap_list *list = list_from_name(cap, name);
if (!list) return;
+ aki_mutex_lock(&list->mutex);
struct cap_list_entry entry;
al_str_clone(&entry.unique_id, unique_id);
- entry.buffer_requested = false;
+ entry.entry = NULL;
entry.errored = false;
+ entry.buffer_requested = false;
al_array_push(list->entries, entry);
if (list->idle && list_skip_internal(cap, list, 1)) {
list->idle = false;
- return;
+ } else {
+ list_pump_internal(cap, list, false);
}
- list_pump_internal(cap, list);
+ aki_mutex_unlock(&list->mutex);
}
bool cap_list_skip(struct cap_runner *cap, str *name, s32 n)
{
struct cap_list *list = list_from_name(cap, name);
if (!list) return false;
- return list_skip_internal(cap, list, n);
+ aki_mutex_lock(&list->mutex);
+ bool ret = list_skip_internal(cap, list, n);
+ aki_mutex_unlock(&list->mutex);
+ return ret;
}
-void cap_list_pump(struct cap_runner *cap, str *name)
+void cap_list_pump(struct cap_runner *cap, str *name, bool buffer)
{
struct cap_list *list = list_from_name(cap, name);
- if (list) list_pump_internal(cap, list);
+ if (!list) return;
+ aki_mutex_lock(&list->mutex);
+ list_pump_internal(cap, list, buffer);
+ aki_mutex_unlock(&list->mutex);
}
bool cap_list_set_completed(struct cap_runner *cap, str *name)
{
struct cap_list *list = list_from_name(cap, name);
if (!list) return false;
+ aki_mutex_lock(&list->mutex);
list->swap = true;
list->idle = !list_skip_internal(cap, list, 1);
+ bool ret = !list->idle && list->swap;
list->swap = false;
- return !list->idle;
+ aki_mutex_unlock(&list->mutex);
+ return ret;
}
static void list_close_internal(struct cap_list *list)
@@ -206,6 +226,7 @@ static void list_close_internal(struct cap_list *list)
al_str_free(&entry->unique_id);
}
al_array_free(list->entries);
+ aki_mutex_destroy(&list->mutex);
al_str_free(&list->name);
}
diff --git a/src/fruits/cap/cap.h b/src/fruits/cap/cap.h
index d522a82..07aa63b 100644
--- a/src/fruits/cap/cap.h
+++ b/src/fruits/cap/cap.h
@@ -4,9 +4,11 @@
#include <al/array.h>
#include <al/str.h>
+#include <aki/thread.h>
struct cap_list_entry {
str unique_id;
+ struct cch_entry *entry;
bool buffer_requested;
bool errored;
};
@@ -14,9 +16,12 @@ struct cap_list_entry {
struct cap_list {
str name;
s32 current;
+ bool forward;
s32 set;
bool idle;
+ bool buffer;
bool swap;
+ struct aki_mutex mutex;
array(struct cap_list_entry) entries;
};
@@ -37,6 +42,6 @@ void cap_init(struct cap_runner *cap, bool (*callback)(void *, u8, str *, str *,
void cap_make_list(struct cap_runner *cap, str *name);
void cap_list_add(struct cap_runner *cap, str *name, str *unique_id);
bool cap_list_skip(struct cap_runner *cap, str *name, s32 n);
-void cap_list_pump(struct cap_runner *cap, str *name);
+void cap_list_pump(struct cap_runner *cap, str *name, bool buffer);
bool cap_list_set_completed(struct cap_runner *cap, str *name);
void cap_close(struct cap_runner *cap);
diff --git a/src/fruits/cmv/cmv2.c b/src/fruits/cmv/cmv2.c
index d8f4fc2..3c70317 100644
--- a/src/fruits/cmv/cmv2.c
+++ b/src/fruits/cmv/cmv2.c
@@ -42,8 +42,6 @@ struct cmv {
#endif
};
-static struct cmv c;
-
static str *default_list = al_str_c("default");
static u8 sink_callback(void *userdata, u8 op, u8 type, void *opaque)
@@ -97,6 +95,10 @@ static u8 sink_callback(void *userdata, u8 op, u8 type, void *opaque)
}
}
break;
+ case CAMU_SINK_SET_BUFFERED: {
+ cap_list_pump(&c->cap, default_list, true);
+ break;
+ }
case CAMU_SINK_START:
switch (type) {
case CAMU_SINK_AUDIO: {
@@ -177,6 +179,7 @@ static bool cap_callback(void *userdata, u8 op, str *name, str *unique_id, void
return camu_sink_local_buffer(&c->sink, unique_id, (struct cch_entry *)opaque);
case CAP_SET:
camu_sink_local_set(&c->sink, unique_id);
+ al_log_info("cmv", "Now playing: %.*s.", AL_STR_PRINTF(unique_id));
break;
case CAP_SWAP:
camu_sink_local_swap(&c->sink, unique_id);
@@ -237,12 +240,14 @@ s32 main(s32 argc, char *argv[])
{
aki_common_init();
+ struct cmv c = { };
+
#if CMV_USE_TUI
if (!tui_init(&c.tui)) {
aki_common_close();
return EXIT_FAILURE;
}
- al_set_print(&c, log_callback);
+ al_set_print(log_callback, &c);
#ifdef HAVE_FFMPEG
camu_lav_set_log_callback(lav_log_callback);
#endif
@@ -297,7 +302,7 @@ s32 main(s32 argc, char *argv[])
#if CMV_USE_TUI
aki_timer_init(&c.timer, &c.loop, timer_callback, &c);
- aki_timer_set_repeat(&c.timer, 0.15);
+ aki_timer_set_repeat(&c.timer, 0.10);
aki_timer_again(&c.timer);
#endif
diff --git a/src/fruits/cmv/tui.c b/src/fruits/cmv/tui.c
index 84a1846..21aeac8 100644
--- a/src/fruits/cmv/tui.c
+++ b/src/fruits/cmv/tui.c
@@ -1,7 +1,6 @@
#include <aki/file.h>
#include <al/log.h>
#include <sys/ioctl.h>
-#include <termios.h>
#include "tui.h"
@@ -31,15 +30,22 @@ bool tui_init(struct cmv_tui *tui)
tui->height = 0;
//tui->prev_lines = 0;
- tui->fd = STDIN_FILENO;
+ tui->fd = fileno(stdin);
tui->out = fdopen(tui->fd, "w");
if (!tui->out) return false;
- setbuf(tui->out, NULL);
tui_global = tui;
aki_mutex_init(&tui->mutex);
signal(SIGWINCH, handle_winch);
+ // Disable buffer.
+ setbuf(tui->out, NULL);
+
+ // Disable echo.
+ tcgetattr(tui->fd, &tui->term);
+ tui->term.c_lflag &= ~ECHO;
+ tcsetattr(tui->fd, 0, &tui->term);
+
al_array_init(tui->log_buffer);
tui->last_pts = 0.0;
@@ -114,5 +120,7 @@ void tui_close(struct cmv_tui *tui)
aki_mutex_destroy(&tui->mutex);
fprintf(tui->out, "\n");
fflush(tui->out);
+ tui->term.c_lflag |= ECHO;
+ tcsetattr(tui->fd, 0, &tui->term);
fclose(tui->out);
}
diff --git a/src/fruits/cmv/tui.h b/src/fruits/cmv/tui.h
index 8cf58c0..fb4215e 100644
--- a/src/fruits/cmv/tui.h
+++ b/src/fruits/cmv/tui.h
@@ -1,18 +1,21 @@
#pragma once
+#include <termios.h>
+
#include "../../bimu/local.h"
#include "../../buffer/clock.h"
struct cmv_tui {
s32 fd;
FILE *out;
+ struct aki_mutex mutex;
+ struct termios term;
bool update_size;
u32 width;
u32 height;
//u32 prev_lines;
array(char *) log_buffer;
f64 last_pts;
- struct aki_mutex mutex;
};
bool tui_init(struct cmv_tui *tui);
diff --git a/src/libclient/meson.build b/src/libclient/meson.build
index a2f23b0..99eabb2 100644
--- a/src/libclient/meson.build
+++ b/src/libclient/meson.build
@@ -1,3 +1,3 @@
-libclient_src = ['client.c', 'resource_client.c']
+libclient_src = ['client.c', 'search.c', 'resource_client.c']
libclient_deps = [shoki]
libclient = declare_dependency(sources: libclient_src, dependencies: libclient_deps)
diff --git a/src/libsink/sink.c b/src/libsink/sink.c
index 50adb40..bae6c77 100644
--- a/src/libsink/sink.c
+++ b/src/libsink/sink.c
@@ -23,6 +23,7 @@ enum {
enum {
ADD_BUFFER = 0,
REMOVE_BUFFER,
+ SET_BUFFERED,
START,
STOP,
TOGGLE_PAUSE,
@@ -77,6 +78,21 @@ static void handle_sink_cmd(struct camu_sink *sink, struct camu_sink_cmd *cmd)
}
break;
}
+ case SET_BUFFERED: {
+ switch (cmd->value.i) {
+ case CAMU_SINK_AUDIO: {
+ sink->callback(sink->userdata, CAMU_SINK_SET_BUFFERED, CAMU_SINK_AUDIO, NULL);
+ break;
+ }
+#ifndef CAMU_SINK_NO_VIDEO
+ case CAMU_SINK_VIDEO: {
+ sink->callback(sink->userdata, CAMU_SINK_SET_BUFFERED, CAMU_SINK_VIDEO, NULL);
+ break;
+ }
+#endif
+ }
+ break;
+ }
case START: {
struct camu_sink *sink = (struct camu_sink *)cmd->opaque;
switch (cmd->value.i) {
@@ -179,6 +195,10 @@ static void add_audio_if_set_and_buffered(struct camu_sink_entry *entry)
if (state == BUFFER_SET_OR_BUFFERED) {
entry->sink->callback(entry->sink->userdata, CAMU_SINK_ADD_BUFFER, CAMU_SINK_AUDIO, &entry->audio.buf);
queue_cmd(entry->sink, (struct camu_sink_cmd){
+ .op = SET_BUFFERED,
+ .value.i = CAMU_SINK_AUDIO
+ });
+ queue_cmd(entry->sink, (struct camu_sink_cmd){
.op = START,
.value.i = CAMU_SINK_AUDIO,
.opaque = entry->sink
@@ -230,6 +250,10 @@ static void audio_buffer_callback(void *userdata, u8 op)
.value.i = CAMU_SINK_AUDIO,
.opaque = entry->sink
});
+ queue_cmd(entry->sink, (struct camu_sink_cmd){
+ .op = SET_BUFFERED,
+ .value.i = CAMU_SINK_VIDEO
+ });
}
break;
}
@@ -243,6 +267,10 @@ static void add_video_if_set_and_buffered(struct camu_sink_entry *entry)
if (state == BUFFER_SET_OR_BUFFERED) {
entry->sink->callback(entry->sink->userdata, CAMU_SINK_ADD_BUFFER, CAMU_SINK_VIDEO, &entry->video.buf);
queue_cmd(entry->sink, (struct camu_sink_cmd){
+ .op = SET_BUFFERED,
+ .value.i = CAMU_SINK_VIDEO
+ });
+ queue_cmd(entry->sink, (struct camu_sink_cmd){
.op = START,
.value.i = CAMU_SINK_VIDEO,
.opaque = entry->sink
@@ -543,6 +571,7 @@ bool camu_sink_local_buffer(struct camu_sink *sink, str *unique_id, struct cch_e
.value.f = 0,
.opaque = entry
});
+ aki_mutex_unlock(&sink->mutex);
return true;
}
@@ -599,17 +628,18 @@ void camu_sink_local_set(struct camu_sink *sink, str *unique_id)
{
aki_mutex_lock(&sink->mutex);
struct camu_sink_entry *entry = entry_from_unique_id(sink, unique_id);
- if (sink->current) {
- if (!camu_clock_is_paused(&sink->current->clock)) {
- camu_clock_pause(&sink->current->clock);
- }
- remove_entry_buffers(sink, sink->current);
- }
+ struct camu_sink_entry *previous = sink->current;
sink->current = entry;
add_audio_if_set_and_buffered(entry);
#ifndef CAMU_SINK_NO_VIDEO
add_video_if_set_and_buffered(entry);
#endif
+ if (previous) {
+ if (!camu_clock_is_paused(&previous->clock)) {
+ camu_clock_pause(&previous->clock);
+ }
+ remove_entry_buffers(sink, previous);
+ }
maybe_cleanup_entries(sink);
aki_mutex_unlock(&sink->mutex);
}
@@ -628,6 +658,6 @@ void camu_sink_local_unload(struct camu_sink *sink, str *unique_id)
{
aki_mutex_lock(&sink->mutex);
struct camu_sink_entry *entry = entry_from_unique_id(sink, unique_id);
- if (entry->state == ENTRY_LOADED) entry->state = ENTRY_DISREGUARDED;
+ if (entry && entry->state == ENTRY_LOADED) entry->state = ENTRY_DISREGUARDED;
aki_mutex_unlock(&sink->mutex);
}
diff --git a/src/libsink/sink.h b/src/libsink/sink.h
index e105245..92c18d9 100644
--- a/src/libsink/sink.h
+++ b/src/libsink/sink.h
@@ -30,6 +30,7 @@ enum {
CAMU_SINK_ADD_BUFFER = 0,
CAMU_SINK_REMOVE_BUFFER,
CAMU_SINK_SWAP_BUFFER,
+ CAMU_SINK_SET_BUFFERED,
CAMU_SINK_START,
CAMU_SINK_STOP,
CAMU_SINK_EXIT
diff --git a/src/shoki/py/providers/twitter.py b/src/shoki/py/providers/twitter.py
index 2fc0faf..4770dda 100644
--- a/src/shoki/py/providers/twitter.py
+++ b/src/shoki/py/providers/twitter.py
@@ -2,7 +2,6 @@ import json
import config
import http.cookiejar
from datetime import timezone
-from socketserver import UDPServer
import log
from provider import Provider
@@ -13,7 +12,7 @@ from query_parser import QueryParser
# Official Twitter API
#from twitter import Twitter2, TwitterError, OAuth
-# GraphQL Scrape API
+# GraphQL API
import snscrape.modules.twitter
from snscrape.base import ScraperException
from snscrape.modules.twitter import (TwitterSearchScraper, TwitterProfileScraper,
diff --git a/src/shoki/py/providers/youtube.py b/src/shoki/py/providers/youtube.py
index f17211e..3cbf0c8 100644
--- a/src/shoki/py/providers/youtube.py
+++ b/src/shoki/py/providers/youtube.py
@@ -1,9 +1,9 @@
import log
-import yt_dlp
from provider import Provider
from search import Search
from post import Post, PostType, Image, Video
from query_parser import QueryParser
+from yt_dlp import YoutubeDL
class YDLLogger():
def debug(self, msg):
@@ -28,24 +28,28 @@ ydl_opts = {
# 'cookiefile': '',
}
-ydl = yt_dlp.YoutubeDL(ydl_opts)
+ydl = YoutubeDL(ydl_opts)
def get_playback_url(data, video=True):
if 'entries' in data:
+ if len(data['entries']) == 0:
+ return None
data = data['entries'][0]
- url = data['formats'][0]['url']
+ if 'formats' not in data:
+ if 'url' in data:
+ return data['url']
+ return None
- '''
- data['formats'] = list(filter(lambda f: 'container' not in f, data['formats']))
+ # Filter out hls temporarily.
+ data['formats'] = list(filter(lambda f: not f['protocol'].startswith('m3u8'), data['formats']))
- data['formats'] = list(filter(
- lambda f: not ('container' in f and (f['container'] in ['mp4_dash', 'webm_dash'])), data['formats']
- ))
- '''
+ if len(data['formats']) == 0:
+ return None
- data['formats'] = list(filter(lambda f: 'manifest_url' not in f, data['formats']))
+ url = data['formats'][0]['url']
+ # audio_ext?
has_audio = list(filter(lambda f: 'acodec' not in f or f['acodec'] != 'none', data['formats']))
if video:
@@ -86,7 +90,10 @@ class YoutubeBase(Search):
self.pages[index] = { 'posts': [], 'list': [] }
res = self.get_info()
if res:
- media = [Video(url=get_playback_url(res))]
+ url = get_playback_url(res)
+ if not url:
+ return False
+ media = [Video(url=url)]
self.pages[index]['posts'].append(Post(type=PostType.POST, unique_id='', url='', title='', text='', media=media))
return True