Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
PHPとRustを組み合わせて音声ファイルをエンコードする話
Search
Shumpei Urabe
February 11, 2020
Technology
5.7k
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
PHPとRustを組み合わせて音声ファイルをエンコードする話
PHPerKaigi 2020
https://phperkaigi.jp/2020/
Shumpei Urabe
February 11, 2020
More Decks by Shumpei Urabe
See All by Shumpei Urabe
放送局の“SIer依存”は終わるのか? 〜Claude Code・Devin時代のAIネイティブ放送DX〜
yaminoma
0
90
AIを活用した放送技術スタートアップの制作現場改革について
yaminoma
0
16k
動画配信技術について
yaminoma
2
1.8k
Multimedia Security Topics
yaminoma
0
2.6k
コロナ禍でのライブストリーミングの変化とテレビ放送の規格について
yaminoma
0
1.2k
今日から分かる Android Audioの全て
yaminoma
0
510
Apple Low-Latency HLSを使った 超低遅延配信について
yaminoma
4
5.3k
今日から分かる AVAudioEngineの全て
yaminoma
4
6.4k
Cross Platform Video Player
yaminoma
0
590
Other Decks in Technology
See All in Technology
スクラムで身についていた動き方を、XPで捉え直してみた
codmoninc
PRO
1
310
AIエージェントの開発・提供におけるセキュリティリスクの論点と対策
flatt_security
2
610
Oracle Cloud Infrastructure IaaS 新機能アップデート 2026/6 - 2026/8
oracle4engineer
PRO
0
120
プロダクトエンジニアに必要な「いい感じ」に作る能力 〜たくさん作れる時代に、どこまで作るかの決め方〜
jnishime_dresscode
2
1.4k
プロダクト思考 × 基盤思考を AIで実現する Compound Engineering
tkc66buzz
1
290
現場に行くだけでは足りない——プロダクトエンジニアが業務の流れを捉える観点と、その鍛え方
takumiengineering
0
330
OpenTelemetry eBPF Instrumentationの舞台裏 / Behind the Scenes of OpenTelemetry eBPF Instrumentation
ymotongpoo
1
220
Microsoft 365 Copilot chat -tekoälypalvelun tietosuojaongelmat
hponka
0
540
Kiro Crewしか勝たん!?
miu_crescent
PRO
0
190
Backstageでつくるセルフサービスな社内開発基盤
kikunosuke75
1
360
AIで開発は速くなったのに、なぜ現場は楽にならないのか 〜あなたの組織のボトルネックを突き止めるワークショップ〜
jacopen
1
280
AI活用の現在地、 ちゃんと見えてますか?/XPfest-2026
visional_engineering_and_design
0
160
Featured
See All Featured
Principles of Awesome APIs and How to Build Them.
keavy
128
18k
Design in an AI World
tapps
1
310
SEO in 2025: How to Prepare for the Future of Search
ipullrank
3
3.8k
The Mindset for Success: Future Career Progression
greggifford
PRO
0
490
The Myth of the Modular Monolith - Day 2 Keynote - Rails World 2024
eileencodes
28
3.6k
AI Search: Where Are We & What Can We Do About It?
aleyda
0
7.9k
jQuery: Nuts, Bolts and Bling
dougneiner
66
8.6k
YesSQL, Process and Tooling at Scale
rocio
174
15k
Technical Leadership for Architectural Decision Making
baasie
3
560
[RailsConf 2023] Rails as a piece of cake
palkan
59
7k
Mind Mapping
helmedeiros
1
350
Reality Check: Gamification 10 Years Later
codingconduct
0
2.3k
Transcript
PHPͱRustΛΈ߹ΘͤͯԻ ϑΝΠϧΛΤϯίʔυ͢Δ PHPerKaigi 2020 LT @yaminoma_tw
Shumpei Urabe (@yaminoma_tw) ͖ͳϑϨʔϜϫʔΫ BEAR.Sunday PHPerݟश͍
PHP FFIͷ͓ͳ͠
FFIͱʁ • PHPҎ֎ͷݴޠͰ࣮͞ΕͨωΠςΟϒίʔυΛݺͼग़͢͜ͱ ͕Ͱ͖ΔΈ • FFIωΠςΟϒ࣮ߦͳͷͰɺύϑΥʔϚϯεͷ্͕ظͰ͖ Δ
PHP FFIͷྺ࢙ • Ҏલ͔ΒPECLͰFFIͷΤΫεςϯγϣϯ͋ͬͨ • ͔͠͠ɺ10Ҏ্ߋ৽͞Ε͍ͯͳ͍ঢ়گͰ์ஔ͞Ε͍ͯͨ
PHP FFIͷྺ࢙ • ͦ͜ͰZendࣾͷDmitry StogovࢯɺlibffiΛ֦ͬͨுΛ։ൃͨ͠ • 20191݄ʹࢍ24ɺର15ͱ͍͏ൺֱతᷮࠩͰPHP 7.4ͷ࠾༻ ͕ܾ·Γɺ͜ͷ֦ு͕ແࣄPHP 7.4ʹऔΓࠐ·Εͨ
• ͦͷ݁ՌɺPECLͷFFIΤΫεςϯγϣϯʹൺΔͱɺΠϯλʔϑΣ ΠεͷΈهड़͢Δ͚ͩͰग़དྷΔΑ͏ʹͳͬͨ
ຊ
PHPͰԻϑΝΠϧΛΤϯίʔυͯ͠ΈΔ • ԻϑΝΠϧͷΤϯίʔυͱ͍͑FFmpeg͕ఆ൪Ͱ͋Δ • FFmpegͷίϚϯυΛexecͰୟ͘ͷ؆୯Ͱ͋Δ͕ɺexecͰ ࣮ߦͨ͘͠ͳ͍ͱ͖͋Δ • PHP୯ମͰԻϑΝΠϧΛΤϯίʔυͰ͖Δͱศརʂ
ͱ͍͏͜ͱͰ࡞Γ·ͨ͠
php-mp3-encoder • https://github.com/yaminoma/php-mp3-encoder • RustͰMP3ͷΤϯίʔμʔͰ͋Δlibmp3lameΛͬͯɺWAVϑΝ Πϧ͔ΒMP3ʹΤϯίʔυ͢Δαϯϓϧ • ͜ͷlibmp3lamebindgenΛͬͯRust͔ΒFFIͰݺͼग़͍ͯ͠Δ
͘͠Έ
wavͷதΛ uint8_t* Ͱ͢ Τϯίʔυͨ͠ϑΝΠϧ໊Λ char* Ͱ͢
PHPͰFFIΛ༗ޮʹͯ͠ΈΔ git clone https://github.com/php/php-src.git cd php-src git checkout PHP-7.4 ./configure
--with-ffi make
PHPͰFFIΛ༗ޮʹͯ͠ΈΔ • σϑΥϧτ ffi.enable=preload ʹͳ͓ͬͯΓɺϓϦϩʔυΛ ߦͬͨؔ·ͨCLIΠϯλʔϑΣΠεͰͷΈFFIػೳΛ༻͢ Δ͜ͱ͕Մೳ • ffi.enable=trueʹ͢ΔͱɺશͯͷFFIͷػೳΛ͏͜ͱ͕ग़དྷΔ
RustͰΤϯίʔυ͢Δ෦Λ࣮͢Δ #[no_mangle] pub extern "C" fn encode(data: *mut u8, length:
u32) -> *const c_char { unsafe { let buf: &mut [u8] = core::slice::from_raw_parts_mut(data, length as usize); let mut ptr = io::Cursor::new(buf); let mut wav_reader = hound::WavReader::new(&mut ptr).unwrap(); let mut data = Vec::new(); for sample in wav_reader.samples() { match sample { Ok(smpl) => data.push(smpl), _ => panic!("failed"), } } let timestamp = Rational64::from_integer(0); let raw_frame = RawFrame { timestamp, data }; let mut encoder = Encoder::new(); let output_file_name = encoder.encode(raw_frame); return CString::new(output_file_name) .expect("failed") .into_raw(); } }
RustͰdylibΛϏϧυͯ͠PHPͰαʔϒ͢Δ $ cargo build --release $ php -d ffi.enable=1 -S
localhost:8000 -t src
μΠφϛοΫϥΠϒϥϦΛಡΈࠐΉ $signature = "const char* encode(uint8_t *data, uint32_t length);"; return
\FFI::cdef( $signature, __DIR__ . "/../target/ release/libmp3encoder.dylib");
freadͰϑΝΠϧΛಡΈऔΔ $file = $_FILES['audio_file']['tmp_name']; $handle = fopen($file, "rb"); $fsize =
filesize($file); $value = fread($handle, $fsize);
FFIͷݺͼग़͠ͱ࣮ߦ $ffi = loadLibrary(); $length = \strlen($value); $buffer = FFI::new(FFI::arrayType($ffi->type('uint8_t'),
[$length])); FFI::memcpy($buffer, $value, $length); $bufferPtr = FFI::cast($ffi->type('uint8_t*'), $buffer); $outputFileName = $ffi->encode($bufferPtr, $length);
݁Ռ • 5ͷۂ͕େମ8ඵ͘Β͍Ͱม͕ऴΘͬͨ • PHPͷFFIͷυΩϡϝϯτ͕ใྔগͳͯ݁͘ߏۤ͠Μͩ • FFI͕༗ޮʹͳ͍ͬͯΕͲͷαʔόͰMP3͕ΤϯίʔυͰ͖ Δʂ
FFIͷকདྷ • ܭࢉྔͷଟ͍ϓϩάϥϜΛFFIͰݺͼग़͢ͱྑ͍͔͠Εͳ͍ • ·ͩ·࣮ͩݧతͳཁૉ͕ଟ͍ͷͰɺϓϩμΫγϣϯϨσΟʔͰ ͳ͍ • ͜Ε͔ΒଞͷݴޠͱΈ߹ΘͤͯPHP͕ͬͱΓ্͕͍ͬͯ ͖͍ͨʂ
͓͠·͍