Сетевое вещание — работаем с кодировками

    Подключившись к Корбине (нет, это не реклама), и ради интереса просматривая их сайт, я наткнулся на большое количество интернет-радиостанций, к коим попытался немедленно пристраститься. Разочарование мое было велико. Я не нашёл ни одного плеера, который бы нормально работал с кодировкой тэгов потока. Последней надеждой был VLC, но он оказался хуже всех — получил только общую информацию о потоке, но не стал получать передаваемую сервером информацию о текущей композиции.
    Mplayer выдал мне в консоль следующее:
    torkvemada@inquisitia-nout ~ $ mplayer 85.21.79.5:8185/listen.pls
    MPlayer 1.0rc2-4.3.3 (C) 2000-2007 MPlayer Team
    CPU: Intel(R) Atom(TM) CPU N270 @ 1.60GHz (Family: 6, Model: 28, Stepping: 2)
    CPUflags: MMX: 1 MMX2: 1 3DNow: 0 3DNow2: 0 SSE: 1 SSE2: 1
    Compiled with runtime CPU detection.
    mplayer: could not connect to socket
    mplayer: No such file or directory
    Failed to open LIRC support. You will not be able to use your remote control.

    Playing 85.21.79.5:8185/listen.pls.
    Resolving 85.21.79.5 for AF_INET6...
    Couldn't resolve name for AF_INET6: 85.21.79.5
    Connecting to server 85.21.79.5[85.21.79.5]: 8185...
    Cache size set to 320 KBytes

    Playing 85.21.79.5:8185/.
    Resolving 85.21.79.5 for AF_INET6...
    Couldn't resolve name for AF_INET6: 85.21.79.5
    Connecting to server 85.21.79.5[85.21.79.5]: 8185...
    Name : 101.ru: Aquarium BG
    Genre : N/A
    Website: www.101.ru
    Public : yes
    Bitrate: 0kbit/s
    Cache size set to 320 KBytes
    Cache fill: 0.00% (0 bytes)
    ICY Info: StreamTitle='ÀÊÂÀÐÈÓÌ - Íàóêè Þíîøåé - 0:00';StreamUrl='';
    Cache fill: 15.00% (49152 bytes)
    Audio file file format detected.
    ==========================================================================
    Forced audio codec: mad
    Opening audio decoder: [libmad] libmad mpeg audio decoder
    AUDIO: 44100 Hz, 2 ch, s16le, 96.0 kbit/6.80% (ratio: 12000->176400)
    Selected audio codec: [mad] afm: libmad (libMAD MPEG layer 1-2-3)
    ==========================================================================
    AO: [pulse] 44100Hz 2ch s16le (2 bytes per sample)
    Video: no video
    Starting playback...
    A: 27.8 (27.8) of -0.0 (unknown) 3.7% 45%
    ICY Info: StreamTitle='ÀÊÂÀÐÈÓÌ - Âåëèêèé Äâîðíèê - 0:00';StreamUrl='';
    A: 212.2 (03:32.2) of -0.0 (unknown) 3.7% 45%
    ICY Info: StreamTitle='ADVBEGIN - ADVBEGIN - 0:00';StreamUrl='';
    A: 213.5 (03:33.5) of -0.0 (unknown) 3.7% 45%
    ICY Info: StreamTitle='ADV_0001 - 0:00';StreamUrl='';
    A: 243.6 (04:03.5) of -0.0 (unknown) 3.7% 45%
    ICY Info: StreamTitle='ADVENG - ADVENG - 0:00';StreamUrl='';
    A: 247.7 (04:07.6) of -0.0 (unknown) 3.7% 45%
    ICY Info: StreamTitle='ÀÊÂÀÐÈÓÌ - Áëþç Ïðîñòîãî ×åëîâåêà - 0:00';StreamUrl='';
    A: 348.7 (05:48.7) of -0.0 (unknown) 3.6% 45%
    Exiting... (Quit)

    Как видим, вся информация получается, но кодировку cp1251 mplayer распознать оказался не в состоянии. Как и все остальные плееры. Схожая ситуация, кстати, с высокой вероятностью повторилась бы в Windows, достаточно было бы только найти поток с UTF-8. Но у нас, к счастью, есть возможность исправить ситуацию. За час копания в исходниках mplayer и пару перекомпиляций (увы, мой атом оставляет желать лучшего в плане скорости компиляции) я набросал маленький патч, который позволит параметром командной строки указать, в какой же кодировке к нам приходит поток и выводит информацию в правильной кодировке. Патч использует iconv, поэтому при желании может быть приспособлен к абсолютно любому плееру, для показа как id3-тэгов, так и информации о потоке, в вашей linux-системе.
    Всё дальнейшее руководство относится к APT-системам (Ubuntu, Debian, возможно, AltLinux etc.), но его легко повторить на произвольной системе.
    Выполняем `apt-get source mplayer`, чтобы получить исходники mplayer.
    Заходим в получившийся каталог (у меня это mplayer-1.0~rc2) и правим файлы:
    • cfg-common.h:
      Добавляем где-нибудь на 90-ой строке
      1. #ifdef USE_ICONV
      2.         {"tagcp", &tag_cp, CONF_TYPE_STRING,  0,  0,  0, NULL},
      3. #endif
    • libass/ass_mp.c:
      Добавляем на 36-ой строке:
      1. #ifdef USE_ICONV
      2. extern char* tag_cp;
      3. #else
      4. static char* tag_cp = 0;
      5. #endif
    • stream/stream.h:
      Добавляем на 302-ую строку:
      1. extern char * tag_cp;
    • stream/http.c:
      Добавляем на 30-ой строке:
      1. #ifdef USE_ICONV
      2. #include <iconv.h>
      3. char *tag_cp = 0;
      4. #endif

      И на 121 строке (после строчки "info[len] = 0;"):
      1. #ifdef USE_ICONV
      2.     iconv_t iconv_converter = (iconv_t)(-1);
      3.     char *outcp = "UTF-8";
      4.     char *incp = tag_cp;
      5.     if (tag_cp && (iconv_converter == (iconv_t)(-1)))
      6.     {
      7.             if ((iconv_converter = iconv_open (outcp, incp)) == (iconv_t)(-1))
      8.             {
      9.                     mp_msg(MSGT_DEMUXER, MSGL_ERR, "ICY: can't open iconv.);
      10.             }
      11.     }       
      12.     if (iconv_converter != (iconv_t)(-1))
      13.     {       
      14.             size_t tmp_conv_len = nlen * 4;
      15.             size_t conv_len = tmp_conv_len;
      16.             size_t tmp_len = nlen;
      17.             char *tmp_info = info;
      18.             char *converted_info = (char*)malloc(conv_len + 1);
      19.             if (!converted_info)
      20.                     mp_msg(MSGT_DEMUXER, MSGL_ERR, "ICY: can't allocate memory.);
      21.             char *tmp_conv_info = converted_info;
      22.             if ((conv_len = iconv(iconv_converter, &tmp_info, &tmp_len, &tmp_conv_info, &tmp_conv_len)) == (size_t)(-1))
      23.             {
      24.                    mp_msg(MSGT_DEMUXER, MSGL_WARN, "ICY: error while iconving info.);
      25.                     free(converted_info);
      26.                     (void)iconv_close(iconv_converter);
      27.             }       
      28.            else    
      29.             {       
      30.                     *tmp_conv_info='\0';
      31.                     free(info);
      32.                     info = converted_info;
      33.                     (void)iconv_close(iconv_converter);
      34.                     iconv_converter = (iconv_t)(-1);
      35.             }
      36.     }
      37. #endif /* USE_ICONV */


    Теперь осталось собрать и установить. Набираем `debuild` и либо получаем ругань на недостающие пакеты (устанавливаем их и запускаем debuild снова), либо через некоторое время имеем несколько собранных деб-пакетов. Устанавливаем: `sudo dpkg -i ../mplayer_1.0~rc2-0ubuntu19+medibuntu1_i386.deb` и фиксируем, чтобы пакетный менеджер не вздумал переустановить пакет из репозитория: `sudo aptitude hold mplayer`.
    Ленивые могут скачать:

    Теперь указываем параметр `tagcp` и наслаждаемся:
    torkvemada@inquisitia-nout ~ $ mplayer -tagcp cp1251 85.21.79.5:8185/listen.pls
    MPlayer 1.0rc2-4.3.3 (C) 2000-2007 MPlayer Team
    CPU: Intel(R) Atom(TM) CPU N270 @ 1.60GHz (Family: 6, Model: 28, Stepping: 2)
    CPUflags: MMX: 1 MMX2: 1 3DNow: 0 3DNow2: 0 SSE: 1 SSE2: 1
    Compiled with runtime CPU detection.
    mplayer: could not connect to socket
    mplayer: No such file or directory
    Failed to open LIRC support. You will not be able to use your remote control.

    Playing 85.21.79.5:8185/listen.pls.
    Resolving 85.21.79.5 for AF_INET6...
    Couldn't resolve name for AF_INET6: 85.21.79.5
    Connecting to server 85.21.79.5[85.21.79.5]: 8185...
    Cache size set to 320 KBytes

    Playing 85.21.79.5:8185/.
    Resolving 85.21.79.5 for AF_INET6...
    Couldn't resolve name for AF_INET6: 85.21.79.5
    Connecting to server 85.21.79.5[85.21.79.5]: 8185...
    Name : 101.ru: Aquarium BG
    Genre : N/A
    Website: www.101.ru
    Public : yes
    Bitrate: 0kbit/s
    Cache size set to 320 KBytes
    Cache fill: 0.00% (0 bytes)
    ICY Info: StreamTitle='АКВАРИУМ - Заповедная Песня - 0:00';StreamUrl='';
    Cache fill: 15.00% (49152 bytes)
    Audio file file format detected.
    ==========================================================================
    Forced audio codec: mad
    Opening audio decoder: [libmad] libmad mpeg audio decoder
    AUDIO: 44100 Hz, 2 ch, s16le, 96.0 kbit/6.80% (ratio: 12000->176400)
    Selected audio codec: [mad] afm: libmad (libMAD MPEG layer 1-2-3)
    ==========================================================================
    AO: [pulse] 44100Hz 2ch s16le (2 bytes per sample)
    Video: no video
    Starting playback...
    A: 14.9 (14.8) of -0.0 (unknown) 6.6% 45%
    ICY Info: StreamTitle='АКВАРИУМ - Песня №2 - 0:00';StreamUrl='';
    A: 19.8 (19.8) of -0.0 (unknown) 6.5% 46%
    Exiting... (Quit)
    AdBlock похитил этот баннер, но баннеры не зубы — отрастут

    Подробнее
    Реклама

    Комментарии 47

      0
      Спасибо за проделанную работу, пригодиться!

      P.S. Не забудьте отправить патчи в апстрим — я думаю, многим пригодится :)
        +4
        Ну к созданному параметру по-хорошему надо прикрутить описание, более строгую обработку и т.д. Плюс на самом деле в результате получается небольшое дублирование кода в mplayer и открытие-закрытие иконва на каждом получении метаинформации. Это непрожорливо, но неоптимально, я бы в апстрим не взял, если честно :) Так что патч в общем-то наколеночный, меня просто очень раздражала невозможность узнать, что сейчас играет.
          0
          Самокритика это хорошо :)
            0
            Лучше всё-таки выслать. Могу помочь с оформлением.
              0
              Ну я выслал, (#449421 на lp), но я бы на их месте не принимал :)
          0
          Напишите разработчикам. Надеюсь они оценят ваш скромный вклад и включат этот код в очередной релиз.
            +1
            вот за это и нужно любить СПО
              +1
              Любить надо людей, способных это УЖЕ сделать)
                +1
                СПО — любить за возможности!
                людей делающих такое — уважать!
                  0
                  Мне мой навык не позволяет реализовать эту возможность. Поэтому не за что любить. А умеющий человек, при желании, может и реалтайм патч для проприетарного и прочего закрытого ПО написать. В комментарии ниже уже обсудили, баги в СПО.
              • НЛО прилетело и опубликовало эту надпись здесь
                  0
                  Увы, Вы абсолютно правы.
                    –1
                    Увы, Вы абсолютно правы.
                      0
                      <offtopic>Данный дубль является характеристикой wifi сети на highload++ :) <offtopic>
                      +2
                      ну баги, они везде
                      только в СПО любой может исправить багу сам, если умееет, а не ждать багфиксов от разработчиков, которым может быть и некогда фиксить такое.
                      • НЛО прилетело и опубликовало эту надпись здесь
                          +1
                          ну вобщем-то я хотел сказать, что СПО дает возможность подогнать под себя любую прогу(если умеешь), не ожидая великих разработчиков.
                            –1
                            … И даёт необходимость точить напильником многие программы (умеешь ли ты это делать или не умеешь), не ожидая великих полутора разработчиков, потому что они уже давно забили на свой проект. :)
                              +1
                              не НЕОБХОДИМОСТЬ, а ВОЗМОЖНОСТЬ :)

                              разницу чувствуете?
                                0
                                Чувствую. И хорошо бы, если б ещё и разработчики чувствовали. А то сейчас, увы, в большинстве случаев скорее необходимость получается, чем возможность.
                            • НЛО прилетело и опубликовало эту надпись здесь
                                +3
                                Что значит неправильно?! Зачем-то же в стандарты продвигается юникод, а не кириллическая кодировка 1251 и ей подобные. Возможно стоит задуматься разработчикам, которые до сих пор широко используют cp1251 и не задумываются о потребителях?..

                                Автору спасибо за проделанную работу и наглядный пример как не пасовать перед неудобствами.
                                • НЛО прилетело и опубликовало эту надпись здесь
                                    +1
                                    Продвигается. Но знаете, когда я защищал диплом и упоминал то, что моё решение соответствует международным стандартам в отличие от, мне преподаватели сказали одну простую вещь: стандарты могут в любой момент измениться. Продвигать будут что-то диаметрально противоположное. А людям надо просто работать.
                                    Так и с национальными кодировками. Они пока еще есть в большом количестве. Поэтому с ними надо работать. Точка.
                                    • НЛО прилетело и опубликовало эту надпись здесь
                                        0
                                        Пацталом. Я бы ещё понял весь пафос, если бы ваши хвалёные проприетарные приложения такого рода, НЕ испытывали бы проблем с кодировками. :) :) Чем вы там онлайнрадио под вендой? Оно теги в кои-8 понимает? А, в 866? Ну, ладно, уж хотя бы в утф-8. Ведь не понимает же, скорее всего. Не смотря на проприетарность. Так и о чём разговор?
                            +2
                            СПО надо любить за то что такой патч может написать любой способный на это, в не СПО этого сделать нельзя. ТАКИЕ баги как написал топик стартер в винде сплошь и рядом, только с utf8 и их там вобще никто не фиксит, не пользователи, не разработчики
                            • НЛО прилетело и опубликовало эту надпись здесь
                                +3
                                Увы, но WMP даже к 12-ой версии не хочет жрать UTF-8 тэги. А его уже не пофиксишь.
                                • НЛО прилетело и опубликовало эту надпись здесь
                                    +1
                                    Мне WMP как-то привычнее и удобнее. А музыка вся лежит на ext3-разделе, соответственно, с UTF-8 тэгами. Потому что линуксовые плееры в свою очередь не любят cp1251. Так и мучаюсь.
                                    +1
                                    Блин он кажется id3v2++ теги просто не читает а видит лишь id3v1, который лишь однобитные кодировки держит. А вообще есть вот это
                                    softsearch.ru/programs/145-193-tag-support-plugin-for-media-player-download.shtml
                                      +1
                                      Описание:
                                      Плагин для Windows Media Player и Windows Media Center, добавляющий возможность поддерживать теги дополнительных музыкальных форматов — M4A/FLAC/OGG/APE/MPC. Позволяет использовать в Windows Media Player и Media Center популярные аудио-форматы, как, например, файлы M4A из мобильных устройств iPod/iTunes, сжимаемые без потери качества форматы Flac, Monkey's Audio (APE), Wav Pack (WV), а также OGG, Optim Frog и другие.

                                      И причём тут утф-тэги?
                                        0
                                        По крайней мере у меня с ogg и flac все впорядке сразу становится :) А вообще взял бы кто SDK медиаплеера и написал бы детектилку id3v2++ тегов
                                    +1
                                    просто так сложилось, что оба поста я сегодня прочитал и не согласен с тобой. я как-бы считаю, что тех кто считает, что спо нужно за что-то ненавидететь, нужно изолировать от общества
                                    • НЛО прилетело и опубликовало эту надпись здесь
                              0
                              Это конечно хорошо, но что будет если тэги уже в UTF8?
                                0
                                Не указывайте параметр. Если параметр -tagcp не указан, перекодировки не производится.
                                +1
                                Как насчет прикрутить enca и не задавать кодировку вручную? Для сабтитров уже давно такое возможно.
                                  0
                                  Можно, но мне не нужно, поэтому не прикручивал. А так делается строчки в 4 вроде как.
                                    0
                                    мне кажется, или автоматическое определение кодировки было бы удобнее геморроя с параметрами командной строки?
                                      0
                                      Enca в любом случае требует указания языка для автоопределения. Поэтому параметр никуда не денется.
                                  +1
                                  Сложно сказать, что правильнее, придерживаться стандартов, которые на бумаге написаны и пытаться их продвигать, или же наоборот стремится и следовать за любыми стандартами де факто. По стандарту написано, что теги должны быть в юникоде, и это обьективно лучше ибо если бы все теги были бы в нем, то с перекодировкой проблем не возникало бы, но вот в реальности обычно теги в cp1251, уж и не знаешь кому спасибо сказать. В опенсорсе к стандартам ревностнее относятся, хорошо это или плохо не могу точно сказать
                                  Кстати есть же ещё проект rusxmms с патченной taglib, которая умеет кодировку автодетектить
                                    0
                                    Эта таглиб, я так подозреваю, предназначена для работы с мп3. А тут метаданные потока.
                                      0
                                      В качестве автодетектилки там какая то внешняя либа идёт. Нечто подобное в Амароке реализовали, но там автодетектилка пока ещё подглючивает. Но в принципе реально думаю лучшим решением было бы использование либы, позволяющей автодетектить кодировку. Такое и в апстрим может быть приняли бы.
                                      Другое мне непонятно, насколько сильна у людей инертность мышления, ну неудобен же mp3 для потокового вещания, и звук на низких битрейтах плоховат и что ещё плохо, там латентность появляется. Есть же более заточеные под это дело кодеки типа aac или ogg, да и почти все современные плееры их держат.
                                      0
                                      А в стандарте мп3, про который ты, очевидно, говоришь, есть три используемых версии id3, и только одна из них явно требует тэгов в utf-8.
                                        0
                                        Аха, но вроде же в файл можно сразу две версии тегов писать, v1 и какую нибудь из v2. Но вообще это не слишком нормально, жаль, что не смогли договорится до одной версии.

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

                                    Самое читаемое