Вот проект, который я обдумывал уже год или два. Учитывая достижения в алгоритмах сжатия звука и компьютерном зрении: можно ли сохранить звук достаточно высокого качества на бумажной ленте?
Для меня это увлекательная концепция. Если рассмотреть всю историю носителей информации, от первых цилиндрических пластинок с гравировкой до магнитной ленты, становится ясно, что достижение высокого качества и надежности хранения данных является одновременно сложной и дорогостоящей задачей. Говоря конкретно о магнитной ленте, проблемы, связанные со сложной механической транспортировкой ленты и чувствительной электроникой, подчеркивают некоторые трудности, с которыми инженеры сталкивались в прошлом.
![]() |
| qrtape |
В этом блоге я демонстрирую систему, которая использует современное компьютерное зрение и сжатие звука для замены сложных механических ленточных транспортеров прошлого. На самом деле мой ленточный транспорт полностью сделан из бумаги и картона (за исключением некоторой электроники, конечно). Я решил назвать эту систему QRTape.
![]() |
| qrtape-плеер |
аппаратное обеспечение
Цель этого проекта — закодировать данные на непрерывной полоске бумаги и прочитать их с помощью стандартной веб-камеры. Чтобы обеспечить это, мне нужно было разработать простой механизм подачи ленты, который бы непрерывно перемещал бумажную ленту перед камерой, чтобы ее можно было последовательно читать.
![]() |
| qrtape крупным планом |
Я решил создать его прототип, используя простой картон, скотч и горячий клей. Первым компонентом системы являются золотники. Медиафайлы загружаются в левую часть проигрывателя и протягиваются через картонную коробку, в которой установлены камера и источник света. Катушка состоит из сердечника из бумажного полотенца, вырезанного по размеру, с приклеенными к нему горячим способом картонными торцевыми крышками.
![]() |
| Исходная катушка QRTape |
Лента проходит через коробку, которая представляет собой платформу, источник света и камеру для выравнивания ленты. Небольшая полоска бумаги распрямляет ленту, когда она входит в коробку, и создает источник натяжения, удерживая ее ровно. Эту функцию обычно выполняет прижимной ролик в системе магнитной ленты.
![]() |
| Шаги сканирования qrtape player |
На другой стороне коробки находится приемная катушка, на которую лента натягивается небольшим шаговым двигателем. Этот шаговый двигатель приводит в движение приемную бобину через привод шкива 1:1, где в качестве ремня используется резиновая лента. Это работает на удивление хорошо, учитывая, насколько это просто. Шаговый двигатель питается от очень простого модуля Arduino, который приводит двигатель в движение с постоянной скоростью, так что перед камерой в секунду проходит 1-2 QR-кода.
![]() |
| привод шагового двигателя |
Есть много возможностей для улучшения аппаратного обеспечения. Самым простым был бы механизм центрирования ленты для уменьшения бокового смещения при ее натяжении на этапе сканирования. Более сложная система будет иметь двигатели с обеих сторон механизма подачи ленты, позволяющие перематывать ленту. В идеальном мире программное обеспечение воспроизведения должно было бы осуществлять управление двигателем с обратной связью, чтобы гарантировать, что коды считываются с правильной скоростью, и, при необходимости, устранять ошибки сканирования, перематывая ленту для повторного считывания.
программное обеспечение
сжатие звука
Если QRTape используется для кодирования аудиоданных, первым шагом является сжатие с помощью кодека OPUS. Я использую кодек с переменным битрейтом. Это позволяет более эффективно сжимать более тихие части исходного материала, в то же время позволяя кодеку превышать номинальный битрейт в периоды высокой энтропии для обеспечения более качественных результатов.
# Encode source FLAC file with 12kbps, VBR stereo OPUS.
aarossig@lithium:~/qrtape$ opusenc --discard-comments --discard-pictures \
--framesize 60 --bitrate 12 \
equalizer.flac equalizer-12k-stereo-vbr.opus
Encoding using libopus 1.3.1 (audio)
-----------------------------------------------------
Input: 44.1kHz 2 channels
Output: 2 channels (2 coupled)
60ms packets, 12kbit/sec VBR
Preskip: 312
Encoding complete
-----------------------------------------------------
Encoded: 4 minutes and 21.84 seconds
Runtime: 5 seconds
(52.37x realtime)
Wrote: 363551 bytes, 4364 packets, 275 pages
Bitrate: 10.7233kbit/s (without overhead)
Instant rates: 2.66667kbit/s to 14.6667kbit/s
(20 to 110 bytes per packet)
Overhead: 3.46% (container+metadata)
Результирующий размер аудиофайла продолжительностью 4 минуты 21 секунда составляет всего 355 КБ. Это невероятно!
поделиться
Формат файлов, создаваемых Qrtape, очень прост. Первые два байта кодируют идентификатор последовательности, позволяющий обнаруживать дубликаты/пробелы в потоке кода. Вторые два байта кодируют размер сегмента. Если применяется заполнение, оно будет одинаковым для всех штрих-кодов, за исключением, возможно, последнего штрих-кода. Следующие байты — это данные, которые необходимо передать, а последние два байта — это CRC16 всего сообщения. Это вторая линия защиты от поврежденного текста. QR-коды используют собственную форму исправления ошибок (ECC), но в случае неправильного считывания CRC помогает предотвратить попадание этих данных в прикладное программное обеспечение. CRC16 мал по сравнению с полезной нагрузкой, закодированной в каждом коде, поэтому накладные расходы разумны.
# Break the source file into 2331 byte chunks.
aarossig@lithium:~/qrtape$ qrtape --encode -s 2331 \
--input equalizer-12k-stereo-vbr.opus -p equalizer_
Generating files from 'equalizer-12k-stereo-vbr.opus' in 2325 byte chunks
Generating chunk 0: offset 0, size 2325, filename 'equalizer_0.bin'
Generating chunk 1: offset 2325, size 2325, filename 'equalizer_1.bin'
Generating chunk 2: offset 4650, size 2325, filename 'equalizer_2.bin'
Generating chunk 3: offset 6975, size 2325, filename 'equalizer_3.bin'
...
Generating chunk 154: offset 358050, size 2325, filename 'equalizer_154.bin'
Generating chunk 155: offset 360375, size 2325, filename 'equalizer_155.bin'
Generating chunk 156: offset 362700, size 851, filename 'equalizer_156.bin'
Finished generating chunks
qr-кодирование
Следующим шагом будет кодирование этих BIN-файлов в QR-коды. Это делается с помощью команды qrencode.
# Encode QR codes with medium ECC.
aarossig@lithium:~/qrtape$ for i in {0..156}; do \
qrencode -8 -m 0 -s 16 -l M \
-r equalizer_$i.bin -o equalizer_$i.png; \
done
Вероятно, это самый простой шаг в этом процессе. Примечательными здесь являются то, что QR-код кодируется в двоичном режиме, границы отключены, размер точки увеличен для обеспечения более четкой печати и включен средний ECC. Результатом является QR-код размером 2953 байта с 2331 байтом содержимого.
печать
Последний этап – печать. У меня есть принтер Brother QL-700, который я использую для хобби. Доступен отличный пакет Brother_ql, который поддерживает печать на этом принтере без использования чашек. Это делает весь процесс простым. Если этот пакет установлен, процесс печати так же прост, как последовательная печать каждого штрих-кода с отключенной функцией резки принтера. Между каждым кодом устанавливается задержка, чтобы предотвратить перегрев принтера.
# Print QR codes in order, in high-dpi mode.
# Leave time for the printer to cool between prints.
aarossig@lithium:~/qrtape$ for i in {0..156}; do \
echo printing $i; \
sudo brother_ql -b pyusb -m QL-700 -p usb://0x04f9:0x2042 \
print -l 62 --600dpi --no-cut equalizer_$i.png; \
sleep 12; \
done
Воспроизведение
Воспроизведение звука осуществляется с помощью одной команды конвейера. Никакие файлы не записываются на диск, а в памяти выполняется лишь небольшая буферизация. Команда qrtape включает функцию декодирования, которая считывает штрих-коды со стандартного ввода и выводит их содержимое на стандартный вывод. Штрих-коды считываются с помощью инструмента под названием zbarcam, который имеет режим, который завершает каждый код командой новой строки и в противном случае выдает двоичные данные на стандартный вывод. Эти две команды объединены для предоставления аудиоданных в mplayer для воспроизведения.
# Playback audio through a decode pipeline with mplayer.
aarossig@cobalt:~$ zbarcam /dev/video0 --prescale=1920x1080 \
--raw -Sdisable -Sqrcode.enable -Sbinary \
| ./qrtape/qrtape -d -s 2331 --allow-skip \
| tee equalizer.opus \
| mplayer -
На первом этапе конвейера штрих-коды считываются с веб-камеры USB с помощью zbarcam. Я использовал Logitech C920, который поддерживает очень короткую минимальную дистанцию фокусировки. Второй шаг декодирует штрих-код с помощью qrtape. Утилите Qrtape разрешено пропускать штрих-коды. Что касается звука, то это приемлемо и проявляется в виде небольшого скачка синхронизации. Это может произойти, если считыватель QR-кода не может прочитать. Следующий шаг записывает файл на диск с помощью t и, наконец, декодирует его со стандартного ввода mplayer. Файл, записанный на диск, можно использовать вместе с файлом после завершения воспроизведения.
последние слова
Этот проект является нормой для моего блога. Если я могу сделать что-то интересное, соединив вместе две несвязанные между собой технологии, будьте уверены, я это сделаю. Я впечатлен результатами. Штрих-код воспроизводится не слишком быстро, и система легко воспроизводит звук довольно хорошего качества.
QR-коды — это простой способ кодирования данных в изображении, и для их декодирования доступно множество программ. Я не уверен, что это наиболее эффективное кодирование, учитывая ограничения проблемы, и подозреваю, что гораздо большей пропускной способности можно было бы добиться с помощью чего-то более оптимизированного для этого приложения. В этой установке свет ограничен, а камера — известная величина. Я подозреваю, что это означает, что на заданную площадь можно поместить больше данных, а также устранить пробелы между кодами.




