Saturday, December 17, 2011

Автоматическая подсветка символов из другого языка в тексте

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

Я написал небольшую веб-страницу, где можно набрать (или вставить) текст, и выбрать, на каком он языке — на русском или на английском. Страница тут же подсвечивает символы английского языка, если текст русский, и, наоборот, символы русского языка, если текст на английском.

Скриншот

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

Практическое же применение может быть, например, если есть какой-то код авторизации, и имеется подозрение, что часть символов в нём может быть на русском (и поэтому код не работает). Эта веб-страница, соответственно, позволяет проверить, так ли это.

Friday, January 07, 2011

testcreator — автоматизация тестирования студентов

Вчера я дописал небольшую программу с веб-интерфейсом; она написана на Django (Python) и позволяет несколько автоматизировать процесс тестирования студентов.

Преподаватель может создать тест — например, по русскому языку или математике. После этого он может добавить к нему нужное количество вопросов и к каждому из вопросов заполнить несколько ответов, при этом он может выбрать один или несколько ответов как «правильные».

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

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

Скриншот

Скриншот

Скриншот

Скриншот

Скриншот

Теперь опишу установку (для Ubuntu 10.10).

Скачать файл, распаковать его к себе (например, в домашний каталог).

Открыть консоль, выполнить sudo su.

apt-get update
apt-get install python-django
apt-get install python-setuptools
apt-get install python-all-dev
easy_install pisa
easy_install reportlab
easy_install html5lib

Перейти в каталог с программой и выполнить syncdb — при этом надо
будет создать суперпользователя, которого можно использовать для входа
в админку, если она для чего-нибудь понадобится (/admin/).

cd testcreator
python manage.py syncdb

И запустить сервер. Он вполне подходит для обычного
использования, но для использования несколькими людьми и вообще
продакшена настоятельно рекомендую обратить внимание в сторону
gunicorn + nginx.

python manage.py runserver

Всё, программа должна быть доступна по следующему адресу.

http://127.0.0.1:8000/

Кстати, там используется unobtrusive javascript. То есть если
JavaScript у пользователя по каким-то причинам выключен, и модные
анимированные эффекты динамически меняющихся страниц у него не
отобразить, то программа у него всё равно работает — просто происходит
дополнительный переход по ссылке.

Вот такая программа получилась. Если у вас есть какие-нибудь мысли по поводу этой программы, буду рад их услышать.

Saturday, November 06, 2010

FLAC encoding to MP3 and Ogg

Okay, so you have a collection of amazing music in FLAC. But your portable media player only supports MP3. That means you have to convert the files before you can put them on your player. And it would be nice to convert whole albums.

If your player supports Ogg, you can simply execute this. It converts each of the .flac files in the current directory to Ogg.

oggenc -q7 *.flac

But how about MP3? LAME is a terrific MP3 encoder, but it doesn’t have an option to convert FLAC files.

Well, fortunately, Linux provides all the needed tools to get the needed combination of programs working together to do something.

for i in *.flac ; do flac -dc "${i}" | lame -b 320 --alt-preset insane - "/home/ml/mp3/${i%.flac}.mp3" ; done

Here we use the “for” cycle of bash to run the “flac” command for each of the .flac files in the current directory. Option -d tells flac to decode the given file and -c tells to write output to the standard output (stdout). LAME has two required arguments: input file and output file. But we can use a hyphen (“-”) for input file to use stdin and for output file to use stdout. In this case LAME has stdin received from flac. To transmit flac’s output to lame’s input we used pipes. Finally, ${i%.flac}.mp3 is a simple bash parameter substitution example. It takes the contents of the i variable, but without the ending “.flac”. Then you can just put .mp3 to the end of the string to make a new file extension.

Wednesday, July 21, 2010

Recording and editing screencasts with recordMyDesktop and Audacity

RecordMyDesktop is a nice tool for screencasting. It allows you to record the computer’s screen and your voice. But what if you want a little more? In my case, I wanted to edit the audio track to include music and change volume on my voice in some places.

Before running recordMyDesktop and recording the video, make sure that you have enough disk space available in /tmp. If you don’t, choose a different working directory using the -workdir option.

This runs the recording after waiting for 5 seconds, and uses /home/kasi_sona/tmp as a temporary files directory.

recordmydesktop --delay 5 --workdir /home/kasi_sona/tmp

To stop the recording, you can use Ctrl + Left Alt + s.

When the video is recorded, it converts to Ogg (Vorbis and Theora). Before the conversion completes, you can go to the temporary files directory and copy the PCM audio file somewhere to edit it with Audacity (you can just make a hardlink using the ln command — a file is deleted only when the last hardlink is deleted).

Then edit the file with Audacity and export it to Ogg Vorbis (you can also select the quality — I like to use 7).

Okay. So, now we have two files. A video file (which includes the original audio track) and an audio file (which we want to use as the new audio track). So, we just want to replace an audio track. All is encoded already, the task seems very simple. And it is very simple, but before I found a solution, I tried a lot of programs (ffmpeg, mencoder, vlc) and none of them worked.

The program that brings a simple, beautiful solution, is called oggzmerge. It is a part of oggz-tools.

This merges out.ogv and voice_with_music.ogg to programming_an_image_hosting_application_with_django.ogg.

oggzmerge -o programming_an_image_hosting_application_with_django.ogg out.ogv voice_with_music.ogg

If you want to have two audio tracks in your video (the user can choose from them), this is the complete solution. For example, if you only included music in your audio track, this allows a user to choose whether he or she wants to hear the background music.

But what if you want to replace the old audio track with a new one? Then you will need to separate audio from video in your original video file. And here is how.

Get oggsplit.

svn checkout http://svn.xiph.org/trunk/ogg-tools/oggsplit/

Of course, you need Subversion for this.

cd oggsplit
./autogen.sh
make

Now split your original video file with oggsplit.

./oggsplit /moar/video/software/django/programming_an_image_hosting_application_with_django/out.ogv

In my case, it created 3 streams: out.c01.g01.ogv, out.c01.g02.ogv, out.c01.g03.ogv.

Move the video stream to your screencast directory and delete other streams.
mv out.c01.g02.ogv /moar/video/software/django/programming_an_image_hosting_application_with_django/only_video.ogv
rm out.c01*

Now go to your screencast’s directory and merge the audio track and the video track.

oggzmerge -o programming_an_image_hosting_application_with_django.ogg only_video.ogv voice_with_music.ogg

Great! Finally, let’s split the video into parts of the needed length. It is useful if you want to upload your screencast on YouTube, but it is longer than 10 minutes.

oggz-chop -o part1.ogg -s 0:0:0 -e 0:10:0 programming_an_image_hostin
g_application_with_django.ogg


Just like oggzmerge, oggz-chop is a part of oggz-tools.

So, here it is. Come on, go record a nice screencast!

Have fun!

Sunday, July 18, 2010

Смотрим кино с субтитрами сразу на двух языках

Увидев только что на Хабрахабре вот эту блогозапись, подумал, а нельзя ли сделать так в Линуксе. Оказалось — можно. Причём метод не зависит от проигрывателя видео, главное, чтобы программа поддерживала субтитры в формате ASS.

Скриншот

if anyone needs this, i created a bash script allowing you to
watch/convert movies with two subtitles shown at the same time. you
may use this if a foreign friend comes to visit you and you both would
like to watch a movie with subtitles in your mother language, for
instance.


Если кому-то надо, я создал скрипт на bash'е, позволяющий смотреть/конвертировать фильмы так, чтобы одновременно показывались две дорожки субтитров. Вы можете им пользоваться, если, скажем, к вам в гости приезжает друг из другой страны, и вы бы оба хотели посмотреть фильм с субтитрами на вашем родном языке.


[MPlayer-users] two subtitles at one time (script)

Я сделал в скрипте изменения в двух строчках, добавив опцию -subcp utf-8 в команду конвертации SRT-файлов.

Зависимости скрипта — mplayer (в случае, если ваши файлы субтитров нужно сконвертировать в srt) и gnu utils (по поводу присутствия gnu utils на компьютере, что-то мне подсказывает, можно не беспокоиться).

Сохраним скрипт merge2ass.sh к себе на компьютер (ссылка выше).

Теперь откроем консоль и перейдём в каталог, в котором находится скрипт.

Например так:
cd scripts/ (находясь в домашнем каталоге)
Или так:
cd ~/scripts/ (находясь где-то ещё)

Установим скрипту права на исполнение (делается один раз):
chmod +x merge2ass.sh

Теперь посмотрим, какие аргументы принимает скрипт.

1. Файл фильма
2. Одни субтитры
2. Вторые субтитры
4. Необязательный аргумент, может быть «-pm» или «--play-movie» для мгновенного перехода к просмотру фильма

Итак, скачиваем русские и английские субтитры.

Русские субтитры, скорее всего, в кодировке CP1251. Меняем кодировку на UTF-8.

iconv -f cp1251 -t utf-8 movies/lie_to_me-s02e11-russian.srt > movies/lie_to_me-s02e11-russian-utf-8.srt

И запускаем скрипт.

./merge2ass.sh movies/lie_to_me-s02e11.avi movies/lie_to_me-s02e11-english.srt movies/lie_to_me-s02e11-russian-utf-8.srt

Скрипт создаёт файл lie_to_me-s02e11-bilingual.ass. Остаётся запустить кино.

mplayer -noautosub -ass movies/lie_to_me-s02e11.avi -sub movies/lie_to_me-s02e11-bilingual.ass -subcp utf-8

Приятного просмотра и, конечно же, изучения языков!

Thursday, October 22, 2009

Linux (или компьютер) совсем для всех

Задача. Обучить (с нуля) 60-летнюю маму пользоваться компьютером, Ubuntu Linux и электронной почтой Gmail.

Ресурс. Все необходимые детали, чтобы собрать компьютер, загрузочная флэшка с Ubuntu, вечер на сборку компьютера и установку ОС, несколько часов на написание руководства, полчаса на обучение.

Результат. Мы переехали в другую страну, а тот компьютер работает и позволяет его пользователю обмениваться письмами по электронной почте без чьей-либо помощи.

Был собран компьютер — процессор Pentium D, 512 MiB оперативной памяти, встроенные в материнскую плату графика и звук, винчестер. Никаких наворотов вроде оптического привода или флоппи-дисковода — в 21-м веке оптические диски (не говоря уж о дискетах) устарели, да и какое отношение они имеют к электронной почте?

Далее на этот компьютер была установлена Ubuntu 9.04. Почти никаких особенностей. Раздел подкачки 1 GiB. Пришлось, правда, сделать небольшую лоботомию при установке — форсировать загрузку Live с графическим драйвером vesa (кажется, параметром vga=788 или как-то так). Очевидно, Ubuntu пробовала какой-то другой драйвер, который, впрочем, успешно вешал компьтер. Такую же проблему я уже встречал ранее на другом компьютере (там тоже было видео ATi, но не встроенное) — там умный подбор «подходящего» драйвера приводил к kernel panic. Впрочем, на большинстве компьютеров, которые я видел, установка Ubuntu проходит вообще без проблем.

После установки всё работало отлично. Эффекты были отключены для увеличения производительности. Звук не работал — нужно было всего-то снести pulseaudio (к этому я уже привык, я вообще считаю, что разработчики Ubuntu очень странные люди в этом плане: зачем встраивать в стабильный дистрибутив то, что работает только на некоторых компьютерах?), после этого всё стало замечательно.

Итак, руководство. При использовании настоятельно рекомендую произвести в нём изменения для конкретного компьютера, конкретной установки Ubuntu и, возможно, адреса электропочты (можно переделать скриншоты).

Например изменения под нюансы компьютера на первой странице руководства:

- нажмите на кнопку включения на корпусе
+ нажмите на кнопку включения на корпусе (она большая)

+ Ваш компьютер имеет нюанс — его включение остановится на определённом этапе. При этом на экране (внизу) появится сообщение: «Intel CPU uCode loading error. Press F1 to Resume». Просто нажмите на клавиатуре клавишу F1 (верхний ряд, вторая слева) и загрузка продолжится.


Ещё неплохо на распечатанном руководстве сделать заметки ручкой — как переключить раскладку клавиатуры, какие логин и пароль вводить. Желательно на соответствующих страницах, чтобы их было просто найти.

Определения
Этот раздел, в принципе, можно не читать. Он содержит всякую занудную компьютерщину, не особо интересную нормальным людям.

Что будет использоваться
Просто перечисление используемых программ.

Приступим
Раздел, показывающий пользователю самые азы. Как включить компьютер? Как запустить веб-браузер? Как ввести текст в поле ввода? Как воспользоваться Гуглом?

Как проверить почту
Тут описывается, как войти в Gmail и проверить почту.

Выключение компьютера
Как правильно выключить компьютер из операционной системы.

Содержание
Содержание руководства.

PDF, 5.7 MiB
ODT, 5.6 MiB

Saturday, December 27, 2008

Легенда о восстановлении Unix

Сейчас много мыслей о том, что ждёт нас в будущем, в 2009 году, да и после. Но почему бы на мгновение не вернутсья в прошлое и не восхититься тем, как хардкорные юниксоиды того времени выкручивались, восстанавливая систему?

Это — перевод статьи Mario Wolczko, опубликованной в Usenet в 1986.

Бывало ли когда-нибудь, что ты оставлял терминал залогиненным, просто чтобы вернуться и увидеть, как (предполагаемый) друг написал в нём rm -rf ~/* и стоит возле клавиатуры: — Одолжи мне пятёрку до четверга, или я нажимаю «энтер».

Без всякого сомнения, этот человек не понимает, какую травму он может нанести, и воспринимает всё как милую шутку.

Это была тихая среда. Если быть точным — среда 1-го октября, 15:15 по британскому летнему времени. Питэр, мой коллега, отошёл от своего терминала и сказал мне: — Марио, у меня тут небольшая проблема с отправкой почты.

Понимая, что такое сообщение может сбить с толку кого угодно, я решил прогуляться до его терминала, чтобы посмотреть, что не так.

В терминале было странное сообщение об ошибке, примерно такое (я уже не помню всех деталей): cannot access /foo/bar for userid 147

Сначала я подумал: у кого userid 147? Отправитель сообщения, получатель или ещё что-то? Тогда я перешёл к другому, уже залогиненному терминалу, и набрал

grep 147 /etc/passwd


просто, чтобы получить ответ
/etc/passwd: No such file or directory.



Тут же я предположил, что чего-то нет. Всё подтвердилось, в ответ на
ls /etc


Я получил
ls: not found.



Я посоветовал Питэру, что хорошей идеей будет ничего сейчас не трогать, и пошёл искать нашего системного администратора.

Когда я пришёл к нему в офис, его дверь была приоткрыта, и в течение 10 секунд я понял, что у нас за проблема. Джэймс, наш менеджер, сидел с головой в руках, руками между коленями, как человек, мир которого только что рухнул. Наш недавно назначенный системный программист, Нэйл, стоял сзади него и пристально, вяло наблюдал за терминалом у него на экране. А я подсмотрел вверху экрана следующее:
# cd
# rm -rf *



Вот дерьмо, подумал я. И это ведь всё объясняет.

Я даже не помню, что происходило в следующие минуты; моя память словно размыта. Я помню только, что мы пробовали ls (снова), ps, who и, может, ещё несколько команд — всё бесполезно. Следующее, что я помню: я снова у моего терминала (многооконный графический терминал), набираю
cd /
echo *


Я должен выразить благодарность Дэвиду Корну, ведь он сделал echo встроенной внутрь командной оболочки; не нужно и говорить, что бинарный файл /bin/echo за компанию со всем /bin был удалён. Что прояснилось в следующие несколько минут, так это то, что /dev, /etc и
/lib неразлучимо исчезли, но, к счастью, Нэйл прервал rm в тот момент, когда она была где-то между /news и /tmp; /usr и
/users остались нетронуты.

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

Мы ведь потеряли не только /etc/restore — все файлы устройств контроллера ленточных накопителей были стёрты. А где живёт mknod? Правильно, /etc. Как насчёт восстановить любой из них по Ethernet с другого VAX? Понятное дело, /bin/tar пропал, а rcp люди из Беркли заботливо положили в
/bin в дистрибутиве 4.3. Кроме того, для работы сети нам нужен как минимум /etc/hosts. Версию cpio мы нашли в /usr/local, но без контроллера ленточных накопителей это, к сожалению, бесполезно.

В качестве альтернативы мы могли бы вытащить загрузочную ленту и пересобрать корневую файловую систему, но ни Джэймс, ни Нэйл никогда не делали этого прежде, и мы не были уверены, что это и есть то, что нам нужно — полностью переформатированный диск и потеря всех наших пользовательских файлов (мы делаем бэкапы пользовательских файлов каждый четверг; по закону Мёрфи всё и должно было случиться именно в среду).
Ещё решение — позаимствовать диск от другого VAX, загрузиться с него, и уже потом разбираться; но тогда бы пришлось звать DEC-инженера — это в самом лучшем случае. У нас было много пользователей, в муках завершающих свои кандидатские диссертации, и потеря возможно недельной работы была немыслима.

Так что же делать? Следующей идеей было написать программу, которая бы создала дескриптор устройства для контроллера ленточных накопителей, но все мы знаем, где живут cc, as и ld. Или, может, сделать минимального вида /etc/passwd, /etc/hosts и прочее, чтобы /usr/bin/ftp смог работать. По счастливой случайности, у меня оказался всё ещё открытый в одном из моих окон gnuemacs — мы могли бы воспользоваться им, чтобы создать passwd и всё остальное, но первым шагом нужно создать директорию, чтобы поместить их туда. Разумеется, был удалён /bin/mkdir, то же самое произошло с /bin/mv, так что мы не могли переименовать /tmp в /etc. Однако это явно была правильная линия для атаки.

К тому моменту к нам присоединился Alasdair, наш местный UNIX-гуру, как оказалось, знающий ассемблер VAX. Так что наш план стал таким:

  1. написать на ассемблере программу, которая бы могла либо переименовать /tmp в /etc, либо создать /etc;

  2. заассемблировать её на другом VAX, сделать uuencode;

  3. записать её в в uu-закодированный файл, используя мой GNU, и сделать uudecode (какой-то умный человек догадался поместить uudecode в /usr/bin).


Остаётся запустить программу. Ещё одно чудо: терминал, который использовался для нанесения ущерба, всё ещё был суперпользовательским после su (достаточно вспомнить, что su находится в /bin), так что у нас хотя бы появился шанс, что всё это заработает.

И вот, мы уже стоим на очаровательном пути к успеху. Потратив всего час, мы состряпали примерно дюжину строчек на ассемблере для создания /etc. Обрезанный бинарный файл оказался длиной всего 76 байт, так что мы сконвертировали его в HEX (читается немного лучше, чем вывод uuencode), и записали, используя мой редактор. Если у вас вдруг когда-нибудь возникнет такая проблема, вот HEX на будущее:


070100002c000000000000000000000000

0000000000000000000000000000000000

dd8fff010000dd8f27000000fb02ef0700

0000fb01ef070000000000bc8f88000400

00bc012f65746300


У меня была подручная программа (а что, у кого-то не было?) для конвертирования ASCII HEX в двоичный код, и вывод /usr/bin/sum совпадал с нашим оригинальным бинарным файлом. Но стоп, секундочку — как же ты установишь права на выполнение без /bin/chmod? За несколько секунд сформированная мысль (которая, как обычно, завершает пару минут раздумий) принесла решение проблемы: нужно записать бинарный файл поверх уже существующего файла, для которого я являюсь владельцем. Вот и хорошо.

Мы вернулись к терминалу с правами суперпользователями, с осторожностью вспомнили поставить umask на 0 (чтобы я мог создавать внутри файлы, используя свой GNU), и запустили бинарный файл. Теперь у нас был /etc, с доступом на запись для всех. Теперь оставалось всего несколько шагов: нужно было создать passwd, hosts, services, protocols, (etc), после чего ftp был готов к работе. Потом мы восстановили содержимое /bin по сети (это невероятно, как тебе начинает жутко не хватать ls после всего нескольких коротких часов без него) и взяли файлы из /etc. Ключевым файлом был /etc/rrestore, с его помощью мы восстановили /dev с бэкап-кассеты. Тут и сказочке конец.

А вот теперь мы задаём себе вопрос, в чём же мораль этой истории. Ну, для начала, стоит хорошо запомнить вечные слова: не паниковать. Мы ведь сначала и хотели просто перезагрузить компьютер и попробовать всё как single-пользователь, но, к сожалению, система при загрузке не нашла бы /etc/init и /bin/sh. Здравое мышление спасло нас от таких действий.

Следующая вещь, которую стоит запомнить, это то, что утилиты UNIX могут использоваться с действительно нетипичными для них целями. Даже без моего gnuemacs мы бы могли выжить, используя, скажем, /usr/bin/grep как замену для /bin/cat.

И последняя вещь. Это невероятно, насколько громадную часть системы можно удалить, не загубив её окончательно. Несмотря на тот факт, что никто бы не смог войти в систему (/bin/login?), и почти все нужные команды пропали, всё остальное выглядело нормально. Естественно, некоторые вещи не могут оставаться живы без, скажем, /etc/termcap, /dev/kmem или /etc/utmp, но, в конечном итоге, всё работает в мире и согласии.

Я оставляю вопрос: оказавшись в такой же ситуации, с возможностью мыслить, учитывая приобретённый теперь опыт, можно было бы решить эту проблему проще?