Slide 1

Slide 1 text

Copyright © OPTiM Corp. All Right Reserved. 1 株式会社 OPTiM R&Dチーム 中村 令和元年にもなって wavファイルをバイナリエディタで読んだ話とか

Slide 2

Slide 2 text

Copyright © OPTiM Corp. All Right Reserved. 2  中村 (なかむら)@ 2016 .10 ~ • 愛媛県松山市生まれ → 九州工業大学(電子情報工学科)→ OPTiM  R&Dチームのエンジニア  学生の頃にやってて役立ったな。と最近思ったこと • 自宅ラックマウント(されてない平積みの)サーバーで遊んだこと • NEC IX2015 ルーターで遊んだこと • Adobe Flash黄金時代に生まれたこと(ActionScriptとの出会い) 自己紹介

Slide 3

Slide 3 text

Copyright © OPTiM Corp. All Right Reserved. 3 アイスブレイク ところでみなさんは 何の(バイナリ)エディタが好きですか?

Slide 4

Slide 4 text

Copyright © OPTiM Corp. All Right Reserved. 4 アイスブレイク 私は最近「0xED」派です https://www.suavetech.com/0xed/0xed.html

Slide 5

Slide 5 text

Copyright © OPTiM Corp. All Right Reserved. 5 アイスブレイク Visual Studio Codeでも読めます(読むだけ)

Slide 6

Slide 6 text

Copyright © OPTiM Corp. All Right Reserved. 6 Copyright © OPTiM Corp. All Right Reserved. WAV と CAF 元年にもなってwavファイルをバイナリエディタで読んだ話とか Ep.1

Slide 7

Slide 7 text

Copyright © OPTiM Corp. All Right Reserved. 7  WAV ( RIFF waveform Audio Format ) • RIFFチャンクとサブチャンクで構成 • 各チャンクの先頭4バイトはチャンク識別子 • RIFF、fmt、data など • fmtチャンク、dataチャンクは必須 • 各チャンクの5バイト目からの4バイトはチャン クサイズ wavファイルの構造 http://soundfile.sapp.org/doc/WaveFormat/

Slide 8

Slide 8 text

Copyright © OPTiM Corp. All Right Reserved. 8 背景 こういう感じのものを作ってました iPhone AVAudioEngine AVAudioRecorder APIサーバー 解析サーバー Go製の普通のAPIサーバー ( http.DetectContentType ) 外部のSaaSなど Validation Error

Slide 9

Slide 9 text

Copyright © OPTiM Corp. All Right Reserved. 9 背景 こういう感じで書いてました

Slide 10

Slide 10 text

Copyright © OPTiM Corp. All Right Reserved. 10 背景 何が出てきたのか caffな何か

Slide 11

Slide 11 text

Copyright © OPTiM Corp. All Right Reserved. 11 背景 caff ? https://developer.apple.com/library/archive/documentation/MusicAudio/Reference/CAFSpec/CAF_overview/CAF_overview.html https://en.wikipedia.org/wiki/Core_Audio_Format  Apple Core Audio Format (CAF) • Mac OS X 10.4以降(条件付きで10.3以降)、iOS 5.0以降でサポートされる • ファイルサイズ制限なし • ヘッダのサイズフィールドが未確定でも大丈夫(録音が中断されてヘッダが未ファイナライズでもOK) • チャンネルレイアウトのようなオーディオデータ以外のデータいろいろ格納できる • 様々なフォーマットのラッパーのように振る舞う(コンテナフォーマットに近い) • 「チャンク」の単位で構成され、チャンクヘッダー + データ部で構成される つまり、出てきたものは「caffのコーデックがLinear PCMになってるファイル」

Slide 12

Slide 12 text

Copyright © OPTiM Corp. All Right Reserved. 12 結論 wavにしたかったら明示しましょう

Slide 13

Slide 13 text

Copyright © OPTiM Corp. All Right Reserved. 13 ちなみに MediaInfo 先生はちゃんと教えてくれてました… https://mediaarea.net/ja/MediaInfo

Slide 14

Slide 14 text

Copyright © OPTiM Corp. All Right Reserved. 14  AMR-NB(Narrowband) • 8000 [Hz] • モノラル 余談 iOS 12.2からiMessageの音声もcaffになった(らしい) https://applech2.com/archives/20190314-imessage-audio-support-opus-in-ios-12-2.html  caff(Opus) • 24000 [Hz] • モノラル

Slide 15

Slide 15 text

Copyright © OPTiM Corp. All Right Reserved. 15 Copyright © OPTiM Corp. All Right Reserved. FLLRチャンク 元年にもなってwavファイルをバイナリエディタで読んだ話とか Ep. 2

Slide 16

Slide 16 text

Copyright © OPTiM Corp. All Right Reserved. 16 背景 こういう感じのものを作ってました(2周目) iPhone AVAudioEngine AVAudioRecorder APIサーバー 解析サーバー Go製の普通のAPIサーバー + github.com/youpy/go-wav Could’t read meta data

Slide 17

Slide 17 text

Copyright © OPTiM Corp. All Right Reserved. 17 背景 こういう感じで書いてました

Slide 18

Slide 18 text

Copyright © OPTiM Corp. All Right Reserved. 18 背景 何が出てきたのか 見慣れない FLLRサブチャンクの 入ったwavファイル

Slide 19

Slide 19 text

Copyright © OPTiM Corp. All Right Reserved. 19 背景 FLLR ? https://stackoverflow.com/questions/6284651/avaudiorecorder-doesnt-write-out-proper-wav-file-header  Apple software often creates WAVE files with a non-standard (but "spec" conformant) • fmtチャンクとdataチャンクの間にFLLRサブチャンクが入る • FLLRチャンクの大きさはデータによって異なるが4KB程度 • wavはRIFFのサブセットのため、サブチャンクが入ることは問題ない • wavのデータ部が44バイト目から始まるような想定で書かれているソフトウェアは正しく動 作しない • dataチャンクの識別子を見つけて、そこをオフセットとしてデータを読む実装でなければならない

Slide 20

Slide 20 text

Copyright © OPTiM Corp. All Right Reserved. 20 背景 youpy/go-wav だめでした

Slide 21

Slide 21 text

Copyright © OPTiM Corp. All Right Reserved. 21 背景 bakape/thumbnailer を使いました https://github.com/bakape/thumbnailer

Slide 22

Slide 22 text

Copyright © OPTiM Corp. All Right Reserved. 22 背景 bakape/thumbnailer  いいところ • FFMPEGをバックエンドにしているのでサブチャンクがあってもきちんと読める • FFMPEGが読めるものをすべて読めるようにするには少し手を加える必要あり? • func NewFFContext(rs io.ReadSeeker) (*FFContext, error) • net/httpパッケージのParseMultipartForm()は32MBを超えるデータは一時ファイルへ書き込まれる • io.Readerを受け取れるものの一時ファイルのパスはパッケージ外で見れない • そして大体のFFMPEGをバックエンドにしてる系のContextはファイルパス(String)を引数にとる

Slide 23

Slide 23 text

Copyright © OPTiM Corp. All Right Reserved. 23 背景 ExtAudioFileWrite()を使うときはご注意を

Slide 24

Slide 24 text

Copyright © OPTiM Corp. All Right Reserved. 24 Copyright © OPTiM Corp. All Right Reserved. AES-CBC と Go と Node.js 元年にもなってwavファイルをバイナリエディタで読んだ話とか Ep.3

Slide 25

Slide 25 text

Copyright © OPTiM Corp. All Right Reserved. 25 背景 こういう感じのものを作ってました テキスト Node.js 標準のCrypto() AES暗号化 UTF-8な 一般的なテキスト 外部のSaaSなど 復号化 Not match テキスト Go crypto/cipher

Slide 26

Slide 26 text

Copyright © OPTiM Corp. All Right Reserved. 26 背景 Q. Node.jsのcrypt()で AES-CBC-256暗号したテキストを Goのcryptoで復号できる?

Slide 27

Slide 27 text

Copyright © OPTiM Corp. All Right Reserved. 27 背景 A. 一部実装しないとできません

Slide 28

Slide 28 text

Copyright © OPTiM Corp. All Right Reserved. 28  AES • ブロック暗号(指定されたブロック長ごとにデータを暗号化) • ブロックの大きさより小さいデータはパディング(何らかの文字で埋める) • パディング方式はPKCSなど 背景 https://kiririmode.hatenablog.jp/entry/20181014/1539473020  goの crypto/cipher や crypto/aes • パディングが未定義 • 暗号化するとき: ブロックサイズの倍数でないとエラー • 復号化するとき: パディング部分を残したまま出力 実装しましょう

Slide 29

Slide 29 text

Copyright © OPTiM Corp. All Right Reserved. 29 背景 大きめのOSS見たら実装してました… https://github.com/hyperledger/fabric-sdk-go

Slide 30

Slide 30 text

Copyright © OPTiM Corp. All Right Reserved. 30 背景 実装しました

Slide 31

Slide 31 text

Copyright © OPTiM Corp. All Right Reserved. 31 Copyright © OPTiM Corp. All Right Reserved. おわりに

Slide 32

Slide 32 text

Copyright © OPTiM Corp. All Right Reserved. 32  フォーマット・仕様、そして実装はきちんと確認しましょう(N回目) • バイナリファイルでも恐れずに • 既存のソースや外部のソースも正しい実装とは限りません • 99%は自分のミスな気が…  けっこう泥臭いこともやります • 欲しいデータセットがない → 自分たちで作る • ライブラリに欲しい機能がない → 自分で実装する おわりに 結局新しいことをやるって、こうなるところありますよね

Slide 33

Slide 33 text

Copyright © OPTiM Corp. All Right Reserved. Copyright © OPTiM Corp. All Right Reserved. 33