image

В данной статье я расскажу о том, как написать плагин на языке C для медиаплеера VLC. Я написал свой плагин для упрощения просмотра сериалов и фильмов на английском языке. Идея создания этого плагина описывается в разделах Идея и Поиск решения. Технические детали реализации плагина приведены в разделах Hello World плагин и Реализация. О том, что получилось в итоге и как этим пользоваться можно прочитать в последнем разделе, Результат.

Исходный код проекта доступен на GitHub.

Идея


Идея изучать иностранный язык за просмотром любимого сериала не нова, но вот с ее воплощением в жизнь лично у меня всегда возникали проблемы. Очень сложно смотреть сериал или фильм, когда не понимаешь половину того, что там говорят. Конечно, можно включить субтитры, но если в речи встретится незнакомое слово или выражение, то от того, что оно будет продублировано текстом, яснее не станет. А смотреть сериал с русскими субтитрами мне совсем не понравилось — мозг переключается на родной язык и перестает воспринимать иностранную речь. Я где-то читал, что сначала нужно смотреть серию на русском языке, а потом уже в оригинале. Но меня такой подход тоже не устроил. Во-первых, где взять столько времени, чтобы по нескольку раз смотреть одно и то же, а во-вторых, смотреть второй раз уже не так интересно — теряется мотивация.

Несмотря на все сложности с просмотром иностранных сериалов, я довольно неплохо могу читать техническую документацию, статьи и книги на английском. Книги мне нравится читать на электронной читалке Kindle, так как там классно реализована функция работы со словарями — можно одним касанием экрана найти перевод незнакомого слова. Англоязычные статьи и сайты удобно читать, установив в браузере специальное расширение для перевода, — я пользуюсь расширением Яндекс.Перевод. Такой подход позволяет читать и понимать английские тексты, не сильно отвлекаясь на поиск незнакомых слов.

Я подумал, почему бы не применить тот же подход для просмотра сериалов — включаем серию на английском, как только встречается непонятная фраза, переключаемся на русскую аудиодорожку и отматываем немного назад. Далее продолжаем смотреть серию на английском.

Поиск решения


На самом деле, вся необходимая мне функциональность уже доступна во многих популярных медиаплеерах. Единственное, мне бы хотелось переключать аудиодорожку и отматывать видео на несколько секунд назад нажатием одной кнопки. Также было бы здорово, если бы после перевода непонятного фрагмента медиаплеер сам переключал аудиодорожку обратно на английскую. Ну и еще неплохо было бы иметь возможность повторять переведенный ранее фрагмент с английской дорожкой. 

То есть, мне нужен медиаплеер, под который можно писать плагины. Желательно еще, чтобы он был кроссплатформенным, так как я пользуюсь ПК под Windows и ноутбуком под Linux. Мой выбор сразу же пал на VLC. На хабре я даже нашел статью, в которой @Idunno рассказывает, как написать расширение VLC на LUA. Кстати, это расширение он тоже написал для изучения английского) К сожалению, данное расширение не работает в последних версиях VLC (старше 2.0.5). Из-за нестабильной работы из LUA API убрали возможность добавления callback-функций, через которые в LUA-расширении можно было обрабатывать события клавиатуры. В README к своему расширению на GitHub @Idunno приводит ссылку на mailing list разработчиков VLC с обсуждением данной проблемы.

Таким образом, для реализации моей идеи расширение на LUA не подойдет, нужно писать плагин на C. И хоть я и писал что-либо на C последний раз лет 7 назад, еще в университете, решил попробовать.

Hello World плагин


Стоит отметить, что у медиаплеера VLC достаточно хорошая документация. Из нее я узнал, что при разработке медиаплеера используется модульный подход. VLC состоит из нескольких независимых модулей, реализующих определенную функциональность, и ядра (libVLCCore), которое управляет этими модулями. При этом модули бывают двух типов: внутренние (in-tree) и внешние (out-of-tree). Исходный код внутренних модулей хранится в одном репозитории с кодом ядра. Внешние модули разрабатываются и собираются независимо от медиаплеера VLC. Собственно, последние и есть то, что называют плагинами.

В документации также есть статья о том, как написать свой плагин (модуль) на языке C. В этой статье приводится исходный код простого плагина, который при запуске VLC выводит на консоль приветственное сообщение «Hello, <name>» (значение <name> берется из настроек плагина). Забегая немного вперед, скажу, что в приведенном примере нужно добавить следующую строчку после set_category(CAT_INTERFACE):

set_subcategory( SUBCAT_INTERFACE_CONTROL )

Отлично, осталось только собрать плагин и протестировать его работу. По сборке внешнего плагина тоже есть инструкция. Тут стоит обратить внимание на раздел Internationalization, в котором описывается, как работает локализация в VLC. Если коротко, то для внешних плагинов требуется определять макросы N_(), _():

#define DOMAIN  "vlc-myplugin"
#define _(str)  dgettext(DOMAIN, str)
#define N_(str) (str)

Для сборки предлагается использовать старый добрый Makefile либо Autotools. Я решил пойти простым путем и выбрал Makefile. В Makefile нужно не забыть определить переменную MODULE_STRING — это идентификатор нашего плагина. Также я немного подправил работу с директориями — теперь они определяются через pkg-config. В итоге получились следующие файлы:

hello.c
/**
 * @file hello.c
 * @brief Hello world interface VLC module example
 */
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif

#define DOMAIN  "vlc-myplugin"
#define _(str)  dgettext(DOMAIN, str)
#define N_(str) (str)
 
#include <stdlib.h>
/* VLC core API headers */
#include <vlc_common.h>
#include <vlc_plugin.h>
#include <vlc_interface.h>
 
/* Forward declarations */
static int Open(vlc_object_t *);
static void Close(vlc_object_t *);
 
/* Module descriptor */
vlc_module_begin()
    set_shortname(N_("Hello"))
    set_description(N_("Hello interface"))
    set_capability("interface", 0)
    set_callbacks(Open, Close)
    set_category(CAT_INTERFACE)
    set_subcategory( SUBCAT_INTERFACE_CONTROL )
    add_string("hello-who", "world", "Target", "Whom to say hello to.", false)
vlc_module_end ()
 
/* Internal state for an instance of the module */
struct intf_sys_t
{
    char *who;
};
 
/**
 * Starts our example interface.
 */
static int Open(vlc_object_t *obj)
{
    intf_thread_t *intf = (intf_thread_t *)obj;
 
    /* Allocate internal state */
    intf_sys_t *sys = malloc(sizeof (*sys));
    if (unlikely(sys == NULL))
        return VLC_ENOMEM;
    intf->p_sys = sys;
 
    /* Read settings */
    char *who = var_InheritString(intf, "hello-who");
    if (who == NULL)
    {
        msg_Err(intf, "Nobody to say hello to!");
        goto error;
    }
    sys->who = who;
 
    msg_Info(intf, "Hello %s!", who);
    return VLC_SUCCESS;
 
error:
    free(sys);
    return VLC_EGENERIC;    
}
 
/**
 * Stops the interface. 
 */
static void Close(vlc_object_t *obj)
{
    intf_thread_t *intf = (intf_thread_t *)obj;
    intf_sys_t *sys = intf->p_sys;
 
    msg_Info(intf, "Good bye %s!", sys->who);
 
    /* Free internal state */
    free(sys->who);
    free(sys);
}

Makefile
LD = ld
CC = cc
PKG_CONFIG = pkg-config
INSTALL = install
CFLAGS = -g -O2 -Wall -Wextra
LDFLAGS =
LIBS =
VLC_PLUGIN_CFLAGS := $(shell $(PKG_CONFIG) --cflags vlc-plugin)
VLC_PLUGIN_LIBS := $(shell $(PKG_CONFIG) --libs vlc-plugin)
VLC_PLUGIN_DIR := $(shell $(PKG_CONFIG) --variable=pluginsdir vlc-plugin)
 
plugindir = $(VLC_PLUGIN_DIR)/misc
 
override CC += -std=gnu99
override CPPFLAGS += -DPIC -I. -Isrc
override CFLAGS += -fPIC
override LDFLAGS += -Wl,-no-undefined,-z,defs
 
override CPPFLAGS += -DMODULE_STRING=\"hello\"
override CFLAGS += $(VLC_PLUGIN_CFLAGS)
override LIBS += $(VLC_PLUGIN_LIBS)
 
all: libhello_plugin.so
 
install: all
	mkdir -p -- $(DESTDIR)$(plugindir)
	$(INSTALL) --mode 0755 libhello_plugin.so $(DESTDIR)$(plugindir)

install-strip:
	$(MAKE) install INSTALL="$(INSTALL) -s"

uninstall:
	rm -f $(plugindir)/libhello_plugin.so

clean:
	rm -f -- libhello_plugin.so src/*.o

mostlyclean: clean
 
SOURCES = hello.c
 
$(SOURCES:%.c=src/%.o): $(SOURCES:%.c=src/%.c)
 
libhello_plugin.so: $(SOURCES:%.c=src/%.o)
	$(CC) $(LDFLAGS) -shared -o $@ $^ $(LIBS)
 
.PHONY: all install install-strip uninstall clean mostlyclean

Проще всего собрать плагин под Linux. Для этого потребуется установить, собственно, сам медиаплеер VLC, а также необходимые для сборки плагина файлы и инструменты. В Debian/Ubuntu это можно сделать с помощью следующей команды:

sudo apt-get install vlc libvlc-dev libvlccore-dev gcc make pkg-config

Собственно, все готово, собираем и устанавливаем наш плагин с помощью команды:

sudo make install

Для проверки работы плагина запускаем VLC также из консоли:

vlc

К сожалению, никакого «Hello world» мы не увидели. Все дело в том, что плагин нужно сначала включить. Для этого открываем настройки (Tools > Preferences), переключаемся на расширенный вид (выбираем All в группе Show settings) и находим в дереве на панели слева Interface > Control interfaces — ставим галочку напротив нашего плагина Hello interface.



Сохраняем настройки и перезапускаем VLC.



Сборка плагина под Windows


С Windows все немного сложнее. Для сборки плагина потребуется скачать sdk, который содержит библиотеки, заголовочные и конфигурационные файлы VLC. Раньше sdk входил в обычную сборку VLC и найти его можно было в папке установки программы. Теперь же он поставляется в виде отдельной сборки медиаплеера. Например, для VLC версии 3.0.8 эту сборку можно скачать по ссылке ftp://ftp.videolan.org/pub/videolan/vlc/3.0.8/win64/vlc-3.0.8-win64.7z (важно скачивать именно 7z-архив).

Копируем содержимое архива в какую-нибудь папку, например, в С:\Projects. Кроме sdk архив содержит и сам медиаплеер, который можно использовать для тестирования и отладки плагина.

Чтобы наш Makefile можно было использовать для сборки и установки плагина, нужно поправить файл C:\Projects\vlc-3.0.8\sdk\lib\pkgconfig\vlc-plugin.pc, указав в переменных prefix и pluginsdir корректный путь до папки с sdk и plugins соответственно:

prefix=/c/Projects/vlc-3.0.8/sdk
pluginsdir=/c/Projects/vlc-3.0.8/plugins

Для сборки под Windows нам также потребуется установить компилятор и другие утилиты. Все необходимое ПО можно получить, установив среду MSYS2. На сайте проекта есть подробная инструкция по установке. Если коротко, то сразу после установки нужно открыть консоль (C:\msys64\msys2.exe) и обновить пакеты MSYS2 с помощью команды:

pacman -Syu

Далее нужно закрыть окно терминала MSYS2, затем открыть его еще раз и выполнить команду

pacman -Su

После обновления всех пакетов нужно установить тулчейн:

pacman -S base-devel mingw-w64-x86_64-toolchain

Теперь, когда все необходимые пакеты установлены, можно приступать к сборке плагина. Я немного доработал Makefile, чтобы он мог собирать плагин как под Linux так и под Windows. Кроме того, пришлось убрать некоторые неподдерживаемые MinGW параметры сборки, в итоге Makefile стал выглядеть так:

Makefile для Windows
LD = ld
CC = cc
PKG_CONFIG = pkg-config
INSTALL = install
CFLAGS = -g -O2 -Wall -Wextra
LDFLAGS =
LIBS =
VLC_PLUGIN_CFLAGS := $(shell $(PKG_CONFIG) --cflags vlc-plugin)
VLC_PLUGIN_LIBS := $(shell $(PKG_CONFIG) --libs vlc-plugin)
VLC_PLUGIN_DIR := $(shell $(PKG_CONFIG) --variable=pluginsdir vlc-plugin)
 
plugindir = $(VLC_PLUGIN_DIR)/misc
 
override CC += -std=gnu99
override CPPFLAGS += -DPIC -I. -Isrc
override CFLAGS += -fPIC
override LDFLAGS += -Wl,-no-undefined
 
override CPPFLAGS += -DMODULE_STRING=\"hello\"
override CFLAGS += $(VLC_PLUGIN_CFLAGS)
override LIBS += $(VLC_PLUGIN_LIBS)
 
SUFFIX := so
ifeq ($(OS),Windows_NT)
    SUFFIX := dll
endif

all: libhello_plugin.$(SUFFIX)
 
install: all
	mkdir -p -- $(DESTDIR)$(plugindir)
	$(INSTALL) --mode 0755 libhello_plugin.$(SUFFIX) $(DESTDIR)$(plugindir)

install-strip:
	$(MAKE) install INSTALL="$(INSTALL) -s"

uninstall:
	rm -f $(plugindir)/libhello_plugin.$(SUFFIX)

clean:
	rm -f -- libhello_plugin.$(SUFFIX) src/*.o

mostlyclean: clean
 
SOURCES = hello.c
 
$(SOURCES:%.c=src/%.o): $(SOURCES:%.c=src/%.c)

libhello_plugin.$(SUFFIX): $(SOURCES:%.c=src/%.o)
	$(CC) $(LDFLAGS) -shared -o $@ $^ $(LIBS)
 
.PHONY: all install install-strip uninstall clean mostlyclean

Так как MSYS2 ничего не знает о нашем sdk для VLC, то перед сборкой нужно добавить в переменную окружения PKG_CONFIG_PATH путь до папки pkgconfig из этого sdk. Открываем консоль MinGW (C:\msys64\mingw64.exec) и выполняем команды:

export PKG_CONFIG_PATH=/c/projects/vlc-3.0.8/sdk/lib/pkgconfig:$PKG_CONFIG_PATH
make install

Для проверки работы плагина запускаем VLC также из консоли:

/c/projects/vlc-3.0.8/vlc

Как и в случае с Linux, идем в настройки и включаем наш плагин. Сохраняем настройки и перезапускаем VLC.

Реализация плагина


Для реализации моего плагина мне необходимо было понять, как управлять медиаплеером (менять аудиодорожку, перематывать назад) и как обрабатывать события нажатия клавиш клавиатуры. Чтобы разобраться во всем этом, я обратился к документации. Также в Интернете я нашел пару интересных статей, проливающих свет на архитектуру медиаплеера: The architecture of VLC media framework и VLC media player API Documentation.

VLC состоит из большого количества независимых модулей (400+). Каждый модуль должен предоставлять информацию о типе реализуемой им функциональности, а также функции инициализации/финализации. Данная информация описывается в блоке vlc_module_begin()vlc_module_end() с помощью макросов set_capability() и set_callbacks(). Функции инициализации/финализации модуля (обычно они называются Open и Close) имеют следующую сигнатуру:

static int Open(vlc_object_t *)
static void Close(vlc_object_t *)

vlc_object_t — это базовый тип для представления данных в VLC, от которого наследуются все остальные (см. статью Object_Management). Указатель на vlc_object_t нужно приводить к конкретному типу данных в соответствии с той функциональностью, которую реализует модуль. Для управления медиаплеером я указал в макросе set_capability() значение interface. Соответственно, в функциях Open и Close мне нужно привести vlc_object_t к intf_thread_t.

Взаимодействие между модулями построено на основе шаблона проектирования observer. VLC предоставляет механизм «object variables» (см. статью Variables), с помощью которого в экземпляры типа vlc_object_t (и его производные) можно добавлять переменные. Через эти переменные модули могут обмениваться данными. Также на переменную можно навесить callback-функцию, которая будет вызываться при изменении значения этой переменной.

В качестве примера можно рассмотреть модуль Hotkeys (modules/control/hotkeys.c), который отвечает за обработку событий нажатия горячих клавиш. В функции Open на переменную key-action навешивается callback-функция ActionEvent:

var_AddCallback( p_intf->obj.libvlc, "key-action", ActionEvent, p_intf );

В функцию var_AddCallback передается указатель на vlc_object_t, имя переменной, callback-функция и указатель на void для передачи произвольных данных, которые потом пробрасываются в указанную callback-функцию. Сигнатура callback-функции приведена ниже.

static int ActionEvent(vlc_object_t *, char const *, vlc_value_t, vlc_value_t, void *)

В качестве параметров в callback-функцию передается указатель на vlc_object_t, имя переменной, старое и новое значение этой переменной (в данном случае, идентификатор соответствующего нажатой комбинации горячих клавиш действия), а также заданный при добавлении callback-функции указатель на какие-либо дополнительные данные.

Непосредственно обработка событий горячих клавиш выполняется в функции PutAction, которая вызывается внутри callback-функции ActionEvent. Функция PutAction принимает на вход идентификатор события нажатия комбинации горячих клавиш (i_action) и с помощью оператора switch выполняет соответствующие действия. 

Например, событию перемотки назад соответствует значение ACTIONID_JUMP_BACKWARD_SHORT. Для выполнения соответствующего действия из настроек VLC берется интервал перемотки (из переменной short-jump-size):

mtime_t it = var_InheritInteger( p_input, varname );

Чтобы перемотать проигрываемый файл, достаточно присвоить переменной time-offset значение, соответствующее времени (в микросекундах), на которое нужно сместить воспроизведение:

var_SetInteger( p_input, "time-offset", it * sign * CLOCK_FREQ );

Для перемотки вперед нужно указать положительное значение, для перемотки назад — отрицательное. Константа CLOCK_FREQ используется для конвертации секунд в микросекунды.

Аналогичным образом происходит смена аудиодорожки (событие ACTIONID_AUDIO_TRACK). Только отвечающая за аудиодорожку переменная audio-es может принимать ограниченный набор значений (в соответствии с имеющимися в проигрываемом файле аудиодорожками). Получить список возможных значений переменной можно с помощью функции var_Change():

vlc_value_t list, list2;
var_Change( p_input, "audio-es", VLC_VAR_GETCHOICES, &list, &list2 );

Помимо списка значений эта функция также позволяет получить список описаний этих значений (в данном случае название аудиодорожек). Теперь мы можем поменять аудиодорожку с помощью функции var_Set():

var_Set( p_input, "audio-es", list.p_list->p_values[i] );

Как управлять медиаплеером разобрались, осталось научиться обрабатывать события клавиатуры. К сожалению, добавить новую горячую клавишу у меня не получилось. Все горячие клавиши жестко зашиты в коде ядра VLC (src/misc/actions.c). Поэтому я добавил обработчик более низкоуровневых событий нажатия клавиш клавиатуры, повесив свою callback-функцию на изменение переменной key-pressed:

var_AddCallback( p_intf->obj.libvlc, "key-pressed", KeyboardEvent, p_intf );

В переменной key-pressed хранится код символа (в Unicode), соответствующего последней нажатой клавише. Например, при нажатии клавиши с цифрой «1» переменной key-pressed будет присвоено значение 49 (0x00000031 в 16ой системе счисления). Посмотреть коды других символов можно на сайте unicode-table.com. Кроме того, в значении переменной key-pressed учитывается нажатие клавиш-модификаторов, для них отведен  четвертый значащий байт. Так, например, при нажатии комбинации клавиш «Ctrl + 1» переменной key-pressed будет присвоено значение 0x04000031 (00000100 00000000 00000000 001100012). Для наглядности в таблице ниже приведены значения различных комбинаций клавиш:
Комбинация клавиш Значение
Ctrl + 1 00000100 00000000 00000000 001100012
Alt + 1 00000001 00000000 00000000 001100012
Ctrl + Alt + 1 00000101 00000000 00000000 001100012
Shift + 1 00000010 00000000 00000000 001000012
Обратите внимание на значение при нажатии комбинации «Shift + 1». Так как в этом случае будет выведен символ «!», то и значение первого байта будет соответствовать коду этого символа в Unicode (0x00000021).

Результат


Я назвал свой плагин TIP — акроним от фразы «translate it, please», также tip можно перевести как «подсказка». Исходный код плагина опубликован на GitHub, там же можно скачать готовые сборки плагина под Windows и Linux.

Для установки плагина нужно скопировать файл libtip_plugin.dll (libtip_plugin.so для Linux) в папку <path-to-vlc>/plugins. В Windows VLC обычно устанавливается в папку C:\Program Files\VideoLAN\VLC. В Linux найти папку установки можно с помощью команды:

whereis vlc

В Ubuntu, например, VLC ставится в /usr/lib/x86_64-linux-gnu/vlc

Далее потребуется перезапустить VLC, затем в главном меню открыть Tools > Preferences, переключиться на расширенный вид (выбрать All в группе Show settings), на панели слева перейти в раздел Interface > Control и поставить галочку напротив пункта TIP (translate it, please). После чего снова потребуется перезапуск VLC.



В настройках плагина можно указать номера основной и вспомогательной (для перевода) аудиодорожек, а также время (в секундах), на которое плагин будет отматывать назад для повтора со вспомогательной аудиодорожкой.



Для управления плагином я добавил следующие горячие клавиши:

  • «/» для перевода
  • «Shift + /» для повтора переведенного ранее фрагмента видео с основной аудиодорожкой

Во время выполнения команд перевода и повтора плагин отображает в верхнем левом углу сообщения «TIP: translate» и «TIP: repeat» соответственно.



По своему опыту использования плагина могу сказать, что, в целом, я доволен результатом. Главное, правильно подобрать контент, если будет понятна хотя бы половина используемой там иностранной речи, плагин поможет перевести остальное. В противном случае плагин, наверное, будет бесполезен.

Комментарии (27)


  1. vanyas
    15.11.2019 17:04

    Жаль это к стриминговым сервисам типа нетфликса не прикрутишь


    1. Tarson
      15.11.2019 17:43

      Можно Java прикрутить к стримингу через фреймворк VLCJ
      Я делал (см. мои публикации), просто стриминг по udp, но там можно что угодно и файлы и RTP протоколы. Плюс кнопки и окна с плеером интегрируются на раз. Похоже, вообще весь command line VLC можно через этот фреймворк прикрутить.


    1. ahnyava
      15.11.2019 21:22

      ororo.tv


    1. Amistad
      16.11.2019 14:20

      Оффтопик. Посоветуйте, как решить обратную задачу стриминга.
      Предположим, есть устройство/компьютер, которое может посылать в интернет до 100 КБ неких данных/секунду.
      Как сохранять этот поток в файлы (FTP сервер или БД) понятно.
      А есть ли какое-нибудь «решение из коробки», чтобы сервер просто получал данные, держал их в RAM-памяти и отдавал всем по запросу?


      1. Calc
        19.11.2019 13:07

        vlc+vls
        посмотреть в сторону vlm
        посмотреть в сторону multicast+igmp
        vlc всё это умеет, информации вроде хватает.
        Если чего то не найдете, то можно покопаться в моих древних исходниках:
        github.com/Calc86/dvr/tree/master/bin/system2/classes/vlc

        Можно посмотреть в сторону gstreamer или icecast (вроде умеет работать с видео)


  1. LibrarianOok
    15.11.2019 18:26

    Жаль, что никаким плагином не исправить корявость собственно переводов.


    1. Lazytech
      16.11.2019 08:11

      Справедливости ради скажу, что корявость при переводе фильмов и сериалов иногда вынужденная, потому что далеко не всегда можно перевести одновременно и кратко, и понятно для целевой аудитории, и в строгом соответствии с оригиналом.


  1. artem_ibragimov
    15.11.2019 21:22
    +1

    Столкнулся с такой же проблемой: с субтитрами читаешь только текст, без них не понимаешь половину.
    В моей реализации проигрывается видео,
    при перемотке назад появляются англ.субтитры,
    при повторной перемотке появляются сдвоенные субтитры.
    После перемотанного фрагмента, субтитры исчезают.


    1. Andrey_Epifantsev
      16.11.2019 03:21
      +1

      А где можно посмотреть вашу реализацию?


      1. artem_ibragimov
        16.11.2019 09:55
        +1

        1. interprise
          16.11.2019 11:40

          Выглядит не плохо, ваш проект открытый или коммерческий?


          1. artem_ibragimov
            16.11.2019 13:06

            неоткрытый и некоммерческий хобби-проект — попробовать react.


            1. interprise
              16.11.2019 13:16

              Может сделать открытым? Я бы хотел воспользоваться, но у вас очень мало видео.


              1. artem_ibragimov
                16.11.2019 14:02

                1. interprise
                  16.11.2019 15:57

                  Благодарю. Попробую этот метод.


  1. aklexel Автор
    15.11.2019 21:34

    Хорошая идея, тоже на базе VLC реализовали? Поделитесь ссылкой)


  1. Alcpp
    16.11.2019 05:55

    Только на втором экране я узнал в чем идея.

    Я подумал, почему бы не применить тот же подход для просмотра сериалов — включаем серию на английском, как только встречается непонятная фраза, переключаемся на русскую аудиодорожку и отматываем немного назад. Далее продолжаем смотреть серию на английском.


    Желаельно такую инфу віносить в шапку.


    1. aklexel Автор
      16.11.2019 07:00

      Спасибо за совет, учту на будущее.


  1. VIRT_nsk
    16.11.2019 08:56

    У меня давно уже есть идея попробовать запустить обе озвучки одновременно, только в разных каналах, например, в левое ухо — русскую, а в правое — оригинал. Естественно, нужно чтобы они были точно синхронизированы. Думаю, восприятие очень быстро приспособится к такому потоку информации и можно будет мысленно переключаться на любую из них когда угодно. Тем более, если услышал что-то незнакомое — можно просто вспомнить что было секунду назад в русском канале. Только никак не получается найти достаточно времени на реализацию, да опыта на С у меня нет. Может кто-нибудь захочет реализовать что-то подобное?


    1. ru1z
      16.11.2019 12:13

      Не приспособится, во-первых, будет каша из звуков (попробуйте учить в толпе), а во вторых переводы неидеальны. Третий контрагумент, то что идея — очень простая, легко до нее додуматься, но при этом ни одной техники обучения языками на этой основе не видно. Кроме того непонятно, чем это лучше субтитров, которые формально как бы используют визуальный канал с большей пропускной способностью. Ну и в заключение — смотреть фильмы для обучения — в принципе малоэффективно, это просто аудирование с ситуативной поддержкой. Обычно фильмы — только подкрепляющее, малоэффективное средство для изучения именно языков, если только это не специальные курсы для обучения.

      Можете для интереса вручную с двух устройств запускать разные дорожки и проверить. Или в любом аудиоредакторе, например, Audacity, заменить одну из аудиодорожек на дорожку из дубляжа. Ну или если хочется более готового решения, то это вероятно можно накодить грубо с помощью ffmpeg trac.ffmpeg.org/wiki/AudioChannelManipulation


      1. VIRT_nsk
        16.11.2019 14:04

        В том то и дело, что нужно синхронизировать обе дорожки(фон должен быть общим), но озвучку не совмещать в один канал, а использовать разные. Каша будет только если обез озвучки смешаны вместе, как раз как в толпе, а тут — четкая речь в каждом(ухе) раздельно. Я легко могу сосредоточиться на одном направлении и внимательно слушать именно оттуда, при этом могу запросто вспомнить что было слышно за последние несколько секунд в другом.

        И это не просто для обучения, изначально уже должны быть некоторые навыки и знания. Это для улучшения восприятия зарубежной речи от носителей языка, часто в профессиональной озвучке. Она лучше воспринимается изначально, хотя и немного дальше от бытового разговора. Это практика, чем больше прослушаешь известные формулировки, тем проще их потом находить в реальном разговоре, это будет происходить уже на автомате, не задумываясь.

        Субтитры хорошо, но они слишком отвлекают от видео.


        1. gearbox
          16.11.2019 14:46

          >Субтитры хорошо, но они слишком отвлекают от видео.
          Определитесь зачем вы смотрите видео?
          Получить удовольствие? Есть три опции — смотреть в переводе, выучить язык и смотреть в оригинале, выучить сами субтитры до просмотра и смотреть зная содержимое.
          Выучить/подтянуть язык? Страдайте.


        1. ru1z
          16.11.2019 15:28

          \\ фон должен быть общим
          Я же написал как это сделать. Берете мультиязыковой фильм (например часто такие в mkv), вытаскиваете дорожки, потом совмещаете в одну стерео-дорожку. Учтите, что перевод может и будет отличаться немного, как и длина фразы. Вот специально для вас, в аудасити, сделал пофразно аудиофайл https://www.mediafire.com/file/xkwingkxu6qnet1/TotoroEN2mandarin.mp3/file из того что подвернулось под руку (одна дорожка английский, вторая китайский). Заняло всего три минуты.

          \\ Это для улучшения восприятия зарубежной речи от носителей языка, часто в профессиональной озвучке.
          Сдается мне что это все рассуждения, без тщательного исследования вопроса. Даже если вам это вдруг помогает, то еще нужно доказать, что это не чисто ваш энтузиазм и то, что другим поможет такой явно затратный вариант.


        1. ru1z
          16.11.2019 17:21

  1. Insighttt
    16.11.2019 22:35

    спасибо, сейчас попробую, думаю полезная вещь.


  1. grey_rat
    17.11.2019 01:02

    А возможно ли под новые браузеры написать плагин VLC не NPAPI? Раньше можно было поставить плагин VLC или WMP и смотреть видео ютуба в плеере прямо на веб-странице. Сейчас ничего похожего нет.
    image


  1. rasswet
    18.11.2019 10:27

    мне нравится идея, когда смотришь без сабов, если не понял, нажал кнопку, появились сабы на двух языках фраз 1-5 назад от текущей. Прочитал, и дальше снова без сабов смотришь. на пазлинглише так сделано, но у них не так уж много сериалов доступных, которые мне интересно.