discord で読み上げ bot をつくる
![tkt](https://res.cloudinary.com/zenn/image/fetch/s--xyLm7jsv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/300d20d9e5.jpeg)
get started はここから
![tkt](https://res.cloudinary.com/zenn/image/fetch/s--xyLm7jsv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/300d20d9e5.jpeg)
こっちにする
![tkt](https://res.cloudinary.com/zenn/image/fetch/s--xyLm7jsv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/300d20d9e5.jpeg)
これ使う
![tkt](https://res.cloudinary.com/zenn/image/fetch/s--xyLm7jsv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/300d20d9e5.jpeg)
example 作れたけど、これはどうやったら動かせるんだ?
![tkt](https://res.cloudinary.com/zenn/image/fetch/s--xyLm7jsv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/300d20d9e5.jpeg)
local serve して、/ping
投げても帰ってこない
![tkt](https://res.cloudinary.com/zenn/image/fetch/s--xyLm7jsv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/300d20d9e5.jpeg)
動かしてるのはこれ
![tkt](https://res.cloudinary.com/zenn/image/fetch/s--xyLm7jsv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/300d20d9e5.jpeg)
さっき動かなかったのは、コマンドが違った説
![tkt](https://res.cloudinary.com/zenn/image/fetch/s--xyLm7jsv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/300d20d9e5.jpeg)
.configure(|c| c.prefix("~")) // set the bot's prefix to "~"
これで設定してた。
ので、コマンドは ~ping
![tkt](https://res.cloudinary.com/zenn/image/fetch/s--xyLm7jsv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/300d20d9e5.jpeg)
voice 再生系の機能もあるっぽい
![tkt](https://res.cloudinary.com/zenn/image/fetch/s--xyLm7jsv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/300d20d9e5.jpeg)
start
で読み取り開始して voice に入室。
それ以降はメッセージの追加を検知して読み取る必要がある。
できるかな、
![tkt](https://res.cloudinary.com/zenn/image/fetch/s--xyLm7jsv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/300d20d9e5.jpeg)
webhook とか設定してないけど、どうやって動いてるのか…
![tkt](https://res.cloudinary.com/zenn/image/fetch/s--xyLm7jsv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/300d20d9e5.jpeg)
このライブラリだと、ボイスチャット系に対応してないかも?
![tkt](https://res.cloudinary.com/zenn/image/fetch/s--xyLm7jsv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/300d20d9e5.jpeg)
そのようなライブラリの1つがSerenityです。これは、オプションを利用できるようにしながら、心配する必要のないものを抽象化するライブラリです。これはDiscordAPIをラップアラウンドし、音声サポートとすべての作業を備えた、ほとんど機能が完全です。
気づいてないだけかも
![tkt](https://res.cloudinary.com/zenn/image/fetch/s--xyLm7jsv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/300d20d9e5.jpeg)
こっちかな
![tkt](https://res.cloudinary.com/zenn/image/fetch/s--xyLm7jsv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/300d20d9e5.jpeg)
m1 でビルドできない
error: failed to run custom build command for `audiopus_sys v0.1.8`
Caused by:
process didn't exit successfully: `/app/target/debug/build/audiopus_sys-688f2c42484975a9/build-script-build` (exit code: 101)
![tkt](https://res.cloudinary.com/zenn/image/fetch/s--xyLm7jsv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/300d20d9e5.jpeg)
ここで同じことで悩んでる人がいた
![tkt](https://res.cloudinary.com/zenn/image/fetch/s--xyLm7jsv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/300d20d9e5.jpeg)
error:
is_x86_feature_detected can only be used on x86 and x86_64 targets.
You can prevent it from being used in other architectures by
guarding it behind a cfg(target_arch) as follows:
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] {
if is_x86_feature_detected(...) { ... }
}
--> /usr/local/cargo/registry/src/github.com-1ecc6299db9ec823/opusic-sys-0.3.4/build.rs:74:13
|
74 | if !std::is_x86_feature_detected!("sse") {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 8 previous errors
For more information about this error, try `rustc --explain E0658`.
error: could not compile `opusic-sys`
To learn more, run the command again with --verbose.
warning: build failed, waiting for other jobs to finish...
error: build failed
それでもだめだった
![tkt](https://res.cloudinary.com/zenn/image/fetch/s--xyLm7jsv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/300d20d9e5.jpeg)
m1 にはまだ早いのか、、、
![tkt](https://res.cloudinary.com/zenn/image/fetch/s--xyLm7jsv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/300d20d9e5.jpeg)
これを clone してきて build しても同じエラーだったので、厳しそう
![tkt](https://res.cloudinary.com/zenn/image/fetch/s--xyLm7jsv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/300d20d9e5.jpeg)
intel mac に切り替えて作業することにする
![tkt](https://res.cloudinary.com/zenn/image/fetch/s--xyLm7jsv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/300d20d9e5.jpeg)
intel
error: failed to run custom build command for `audiopus_sys v0.1.8`
Caused by:
process didn't exit successfully: `/app/target/debug/build/audiopus_sys-e2d1122e6f3b14ab/build-script-build` (exit code: 101)
--- stdout
cargo:info=No feature or environment variable found, linking by default.
cargo:rerun-if-env-changed=OPUS_NO_PKG_CONFIG
cargo:rerun-if-env-changed=PKG_CONFIG
cargo:rerun-if-env-changed=PKG_CONFIG_PATH_x86_64-unknown-linux-musl
cargo:rerun-if-env-changed=PKG_CONFIG_PATH_x86_64_unknown_linux_musl
cargo:rerun-if-env-changed=HOST_PKG_CONFIG_PATH
cargo:rerun-if-env-changed=PKG_CONFIG_PATH
cargo:rerun-if-env-changed=PKG_CONFIG_LIBDIR_x86_64-unknown-linux-musl
cargo:rerun-if-env-changed=PKG_CONFIG_LIBDIR_x86_64_unknown_linux_musl
cargo:rerun-if-env-changed=HOST_PKG_CONFIG_LIBDIR
cargo:rerun-if-env-changed=PKG_CONFIG_LIBDIR
cargo:rerun-if-env-changed=PKG_CONFIG_SYSROOT_DIR_x86_64-unknown-linux-musl
cargo:rerun-if-env-changed=PKG_CONFIG_SYSROOT_DIR_x86_64_unknown_linux_musl
cargo:rerun-if-env-changed=HOST_PKG_CONFIG_SYSROOT_DIR
cargo:rerun-if-env-changed=PKG_CONFIG_SYSROOT_DIR
cargo:info=`pkg_config` could not find `Opus`.
cargo:info=Opus source path: "/usr/local/cargo/registry/src/github.com-1ecc6299db9ec823/audiopus_sys-0.1.8/opus".
cargo:info=Opus will be built as static-library.
Updating build configuration files, please wait....
--- stderr
autogen.sh: line 14: autoreconf: not found
thread 'main' panicked at 'Failed to autogen Opus.', /usr/local/cargo/registry/src/github.com-1ecc6299db9ec823/audiopus_sys-0.1.8/build.rs:102:9
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
warning: build failed, waiting for other jobs to finish...
error: build failed
依存してる何かが入ってない?
![tkt](https://res.cloudinary.com/zenn/image/fetch/s--xyLm7jsv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/300d20d9e5.jpeg)
alpine でできるかは不明
![tkt](https://res.cloudinary.com/zenn/image/fetch/s--xyLm7jsv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/300d20d9e5.jpeg)
/app # apk add libopus-dev
fetch http://dl-cdn.alpinelinux.org/alpine/v3.12/main/x86_64/APKINDEX.tar.gz
fetch http://dl-cdn.alpinelinux.org/alpine/v3.12/community/x86_64/APKINDEX.tar.gz
ERROR: unsatisfiable constraints:
libopus-dev (missing):
required by: world[libopus-dev]
どういうこっちゃ
![tkt](https://res.cloudinary.com/zenn/image/fetch/s--xyLm7jsv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/300d20d9e5.jpeg)
apk add opus
したらビルドが通った
![tkt](https://res.cloudinary.com/zenn/image/fetch/s--xyLm7jsv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/300d20d9e5.jpeg)
/app # cargo run
Compiling app v0.1.0 (/app)
Finished dev [unoptimized + debuginfo] target(s) in 15.70s
Running `target/debug/app`
speach is connected!
Segmentation fault
~join
したら落ちた。まだいろいろいるのかも
![tkt](https://res.cloudinary.com/zenn/image/fetch/s--xyLm7jsv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/300d20d9e5.jpeg)
RUN apk update && \
apk upgrade && \
apk add --update --no-cache alpine-sdk git opus-dev build-base autoconf automake libtool m4 ffmpeg
これだけ入れてもだめっぽい
![tkt](https://res.cloudinary.com/zenn/image/fetch/s--xyLm7jsv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/300d20d9e5.jpeg)
alpine だとダメかもなので ubuntu のイメージ引っ張ってくる
![tkt](https://res.cloudinary.com/zenn/image/fetch/s--xyLm7jsv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/300d20d9e5.jpeg)
FROM rust:alpine3.12
WORKDIR /app
RUN apk update && \
apk upgrade && \
apk add --update --no-cache alpine-sdk git opus-dev build-base autoconf automake libtool m4 ffmpeg
ENV FFMPEG_CORE="bash \
tzdata \
libass \
libstdc++ \
libpng \
libjpeg \
xvidcore \
x264-libs \
x265 \
libvpx \
libvorbis \
opus \
lame \
fdk-aac \
freetype \
libavc1394 \
yasm"
ENV RUNTIME_DEPS="coreutils \
make \
cmake \
gcc \
g++ \
clang \
linux-headers \
git \
curl"
ENV BUILD_DEPS="fdk-aac-dev \
freetype-dev \
x264-dev \
x265-dev \
yasm-dev \
libogg-dev \
libvorbis-dev \
opus-dev \
libvpx-dev \
lame-dev \
xvidcore-dev \
libass-dev \
openssl-dev \
musl-dev \
build-base \
libjpeg-turbo-dev \
libpng-dev \
libavc1394-dev \
libavc1394-dev \
clang-dev"
ENV FFMPEG_VERSION=4.0
# FFMPEG
RUN apk update && \
apk add --no-cache apk-tools && \
echo http://nl.alpinelinux.org/alpine/edge/testing >> /etc/apk/repositories && \
apk update && \
apk add --no-cache --virtual .runtime-deps ${RUNTIME_DEPS} && \
apk add --no-cache ${FFMPEG_CORE} && \
apk add --no-cache --virtual .build-deps ${BUILD_DEPS}
COPY Cargo.lock Cargo.lock
COPY Cargo.toml Cargo.toml
COPY . .
CMD [ "/bin/sh", "-c", "cargo run" ]
これでもだめだった
![tkt](https://res.cloudinary.com/zenn/image/fetch/s--xyLm7jsv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/300d20d9e5.jpeg)
あきらめて ubuntu
![tkt](https://res.cloudinary.com/zenn/image/fetch/s--xyLm7jsv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/300d20d9e5.jpeg)
うごいた
![tkt](https://res.cloudinary.com/zenn/image/fetch/s--xyLm7jsv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/300d20d9e5.jpeg)
Voiceのとこが動かんかったので、次は再生のexampleそのままとってきてちゃれんじ
![tkt](https://res.cloudinary.com/zenn/image/fetch/s--xyLm7jsv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/300d20d9e5.jpeg)
参考が増えた
![tkt](https://res.cloudinary.com/zenn/image/fetch/s--xyLm7jsv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/300d20d9e5.jpeg)
できたらここにのせたい
![tkt](https://res.cloudinary.com/zenn/image/fetch/s--xyLm7jsv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/300d20d9e5.jpeg)
CoefontStudioつかいたい
![tkt](https://res.cloudinary.com/zenn/image/fetch/s--xyLm7jsv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/300d20d9e5.jpeg)
youtube の音流すのはできたので
- message 読み取り
- 音声変換
- lambda に乗せてみる
![tkt](https://res.cloudinary.com/zenn/image/fetch/s--xyLm7jsv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/300d20d9e5.jpeg)
lambda には果たして乗るのだろうか
![tkt](https://res.cloudinary.com/zenn/image/fetch/s--xyLm7jsv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/300d20d9e5.jpeg)
厳しそうな予感はする
![tkt](https://res.cloudinary.com/zenn/image/fetch/s--xyLm7jsv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/300d20d9e5.jpeg)
/
入れてられないので厳しい
![tkt](https://res.cloudinary.com/zenn/image/fetch/s--xyLm7jsv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/300d20d9e5.jpeg)
rust が動く安いコンテナ探すか…
![tkt](https://res.cloudinary.com/zenn/image/fetch/s--xyLm7jsv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/300d20d9e5.jpeg)
ローカルで動かして、youtube の url いれたら音が流れるようにはなった
![tkt](https://res.cloudinary.com/zenn/image/fetch/s--xyLm7jsv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/300d20d9e5.jpeg)
ローカルで動かして、youtube の url いれたら音が流れるようにはなった
![tkt](https://res.cloudinary.com/zenn/image/fetch/s--xyLm7jsv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/300d20d9e5.jpeg)
今回は音声ファイルを取得してきてそれを流したいけど、やり方がよくわからない
![tkt](https://res.cloudinary.com/zenn/image/fetch/s--xyLm7jsv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/300d20d9e5.jpeg)
let ffmpeg = Command::new("ffmpeg")
.args(pre_args)
.arg("-i")
.arg("-")
.args(&ffmpeg_args)
.stdin(youtube_dl.stdout.ok_or(Error::Stdout)?)
.stderr(Stdio::null())
.stdout(Stdio::piped())
.spawn()?;
let metadata = Metadata::from_ytdl_output(value?);
trace!("ytdl metadata {:?}", metadata);
Ok(Input::new(
true,
child_to_reader::<f32>(ffmpeg),
Codec::FloatPcm,
Container::Raw,
Some(metadata),
))
input を作れば流せるみたいだけど、それを作ってるのが独自手法過ぎて(?)よくわからん
![tkt](https://res.cloudinary.com/zenn/image/fetch/s--xyLm7jsv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/300d20d9e5.jpeg)
ローカルファイルからinputを作る方法で簡単なのがないか探す
![tkt](https://res.cloudinary.com/zenn/image/fetch/s--xyLm7jsv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/300d20d9e5.jpeg)
input はこれ
![tkt](https://res.cloudinary.com/zenn/image/fetch/s--xyLm7jsv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/300d20d9e5.jpeg)
// Input
pub fn new(
stereo: bool,
reader: Reader,
kind: Codec,
container: Container,
metadata: Option<Metadata>
) -> Self
pub enum Reader {
Pipe(BufReader<ChildContainer>),
Memory(Catcher<Box<Reader>>),
Compressed(TxCatcher<Box<Input>, OpusCompressor>),
Restartable(Restartable),
File(BufReader<File>),
Vec(Cursor<Vec<u8>>),
Extension(Box<dyn Read + Send>),
ExtensionSeek(Box<dyn ReadSeek + Send>),
}
pub enum Codec {
Opus(OpusDecoderState),
Pcm,
FloatPcm,
}
pub enum Codec {
Opus(OpusDecoderState),
Pcm,
FloatPcm,
}
pub struct Metadata {
pub title: Option<String>,
pub artist: Option<String>,
pub date: Option<String>,
pub channels: Option<u8>,
pub start_time: Option<Duration>,
pub duration: Option<Duration>,
pub sample_rate: Option<u32>,
pub source_url: Option<String>,
pub thumbnail: Option<String>,
}
enum 多めだしなんとかなりそう…?
![tkt](https://res.cloudinary.com/zenn/image/fetch/s--xyLm7jsv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/300d20d9e5.jpeg)
厳しかったら ffmpeg 経由でやる
![tkt](https://res.cloudinary.com/zenn/image/fetch/s--xyLm7jsv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/300d20d9e5.jpeg)
metadata 見てると曲であること前提の構造に見えて、喋らせたいとかの場合これではないので貼って思えてきた
![tkt](https://res.cloudinary.com/zenn/image/fetch/s--xyLm7jsv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/300d20d9e5.jpeg)
use songbird::{driver::Driver, ffmpeg, tracks::create_player};
// A Call is also valid here!
let mut handler: Driver = Default::default();
let source = ffmpeg("../audio/my-favourite-song.mp3")
.await
.expect("This might fail: handle this error!");
let (mut audio, audio_handle) = create_player(source);
audio.set_volume(0.5);
handler.play_only(audio);
// Future access occurs via audio_handle.
それっぽいのがあった
![tkt](https://res.cloudinary.com/zenn/image/fetch/s--xyLm7jsv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/300d20d9e5.jpeg)
とりあえずこれでローカルファイルが流せるかやってみる
![tkt](https://res.cloudinary.com/zenn/image/fetch/s--xyLm7jsv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/300d20d9e5.jpeg)
ffmpeg とか youtube-dl とか使ってるのがメインだから、rust じゃなくていいのでは?
とか思っちゃったけど、今は考えてはいけない
![tkt](https://res.cloudinary.com/zenn/image/fetch/s--xyLm7jsv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/300d20d9e5.jpeg)
play_only
を呼び出したい
Methods from Deref<Target = Driver>
これはどうやって呼び出すのか
Rust 力が足りない
![tkt](https://res.cloudinary.com/zenn/image/fetch/s--xyLm7jsv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/300d20d9e5.jpeg)
ソースで定義見ると、ちゃんと impl されてる
![tkt](https://res.cloudinary.com/zenn/image/fetch/s--xyLm7jsv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/300d20d9e5.jpeg)
/// The Call handler is responsible for a single voice connection, acting
/// as a clean API above the inner state and gateway message management.
///
/// If the `"driver"` feature is enabled, then a Call exposes all control methods of
/// [`Driver`] via `Deref(Mut)`.
///
/// [`Driver`]: struct@Driver
driver を enable しないとだめ?
![tkt](https://res.cloudinary.com/zenn/image/fetch/s--xyLm7jsv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/300d20d9e5.jpeg)
ソース追ってたらいつの間にか使えるようになってた
ロードできてなかっただけ?
![tkt](https://res.cloudinary.com/zenn/image/fetch/s--xyLm7jsv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/300d20d9e5.jpeg)
handler.play(track);
だと再生できなかった
次は
handler.enque(track);
で試す
![tkt](https://res.cloudinary.com/zenn/image/fetch/s--xyLm7jsv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/300d20d9e5.jpeg)
input どうやって作るんだって言ってたけど
/// Opens an audio file through `ffmpeg` and creates an audio source.
///
/// This source is not seek-compatible.
/// If you need looping or track seeking, then consider using
/// [`Restartable::ffmpeg`].
///
/// [`Restartable::ffmpeg`]: crate::input::restartable::Restartable::ffmpeg
pub async fn ffmpeg<P: AsRef<OsStr>>(path: P) -> Result<Input> {
_ffmpeg(path.as_ref()).await
}
これでいけそう
![tkt](https://res.cloudinary.com/zenn/image/fetch/s--xyLm7jsv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/300d20d9e5.jpeg)
handler.play(track);
だと再生できなかった
次は
handler.enque(track);
で試す
ファイルパスの指定が間違っていた可能性が大
![tkt](https://res.cloudinary.com/zenn/image/fetch/s--xyLm7jsv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/300d20d9e5.jpeg)
async fn get_input_from_local() -> Input {
let root = option_env!("CARGO_MANIFEST_DIR").unwrap();
let path = Path::new(root);
let file_path = path.join("binaries").join("2_23_AM_2.mp3");
return ffmpeg(file_path)
.await
.expect("This might fail: handle this error!");
}
project root の取得と Input への変換
これを enqueue_source
で再生に成功
![tkt](https://res.cloudinary.com/zenn/image/fetch/s--xyLm7jsv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/300d20d9e5.jpeg)
これで GCP の環境を作った
![tkt](https://res.cloudinary.com/zenn/image/fetch/s--xyLm7jsv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/300d20d9e5.jpeg)
これでできそうな気もするけど、なんとも言えない
![tkt](https://res.cloudinary.com/zenn/image/fetch/s--xyLm7jsv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/300d20d9e5.jpeg)
use google_texttospeech1::Texttospeech;
use google_texttospeech1::{api::ListVoicesResponse, client, Error, Result};
use std::default::Default;
use yup_oauth2;
pub async fn get_speech() -> client::Result<(hyper::Response<hyper::body::Body>, ListVoicesResponse)>
{
let secret: yup_oauth2::ApplicationSecret = Default::default();
let auth = yup_oauth2::InstalledFlowAuthenticator::builder(
secret,
yup_oauth2::InstalledFlowReturnMethod::HTTPRedirect,
)
.build()
.await
.unwrap();
let mut hub = Texttospeech::new(
hyper::Client::builder().build(hyper_rustls::HttpsConnector::with_native_roots()),
auth,
);
hub.voices().list().language_code("magna").doit().await
}
#[cfg(test)]
mod tests {
use super::*;
#[tokio::test]
async fn get() {
let result = get_speech().await;
match result {
Err(e) => match e {
// The Error enum provides details about what exactly happened.
// You can also just use its `Debug`, `Display` or `Error` traits
Error::HttpError(_)
| Error::Io(_)
| Error::MissingAPIKey
| Error::MissingToken(_)
| Error::Cancelled
| Error::UploadSizeLimitExceeded(_, _)
| Error::Failure(_)
| Error::BadRequest(_)
| Error::FieldClash(_)
| Error::JsonDecodeError(_, _) => println!("{}", e),
},
Ok(res) => println!("Success: {:?}", res),
}
}
}
$ cargo test
Compiling app v0.1.0 (/workspace)
.
.
.
test tts::tests::get ... test tts::tests::get has been running for over 60 seconds
サンプル通そうとしてるけど、応答さえない
![tkt](https://res.cloudinary.com/zenn/image/fetch/s--xyLm7jsv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/300d20d9e5.jpeg)
lib 使わずにやった方が早そう
![tkt](https://res.cloudinary.com/zenn/image/fetch/s--xyLm7jsv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/300d20d9e5.jpeg)
Http Client は使えたのでこれを使ってやっていく
![tkt](https://res.cloudinary.com/zenn/image/fetch/s--xyLm7jsv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/300d20d9e5.jpeg)
aws polly の選択肢もありそう
これはライブラリがあった![tkt](https://res.cloudinary.com/zenn/image/fetch/s--xyLm7jsv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/300d20d9e5.jpeg)
aws polly の選択肢もありそう
これはライブラリがあった![tkt](https://res.cloudinary.com/zenn/image/fetch/s--xyLm7jsv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/300d20d9e5.jpeg)
こっちもちょっと試してみよう
![tkt](https://res.cloudinary.com/zenn/image/fetch/s--xyLm7jsv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/300d20d9e5.jpeg)
こっちもちょっと試してみよう
![tkt](https://res.cloudinary.com/zenn/image/fetch/s--xyLm7jsv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/300d20d9e5.jpeg)
これもある
![tkt](https://res.cloudinary.com/zenn/image/fetch/s--xyLm7jsv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/300d20d9e5.jpeg)
stars は少ないけど、 init が 2months ago でこれから伸びてきそう
こっちつかってみる
![tkt](https://res.cloudinary.com/zenn/image/fetch/s--xyLm7jsv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/300d20d9e5.jpeg)
example
![tkt](https://res.cloudinary.com/zenn/image/fetch/s--xyLm7jsv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/300d20d9e5.jpeg)
使うAPIとしてはこれで良いはず
![tkt](https://res.cloudinary.com/zenn/image/fetch/s--xyLm7jsv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/300d20d9e5.jpeg)
running 1 test
I can speak as: Lotte in "Dutch"
I can speak as: Maxim in "Russian"
I can speak as: Salli in "US English"
I can speak as: Geraint in "Welsh English"
I can speak as: Miguel in "US Spanish"
I can speak as: Marlene in "German"
I can speak as: Giorgio in "Italian"
I can speak as: Inês in "Portuguese"
I can speak as: Zeina in "Arabic"
I can speak as: Zhiyu in "Chinese Mandarin"
I can speak as: Gwyneth in "Welsh"
I can speak as: Karl in "Icelandic"
I can speak as: Joanna in "US English"
I can speak as: Lucia in "Castilian Spanish"
I can speak as: Cristiano in "Portuguese"
I can speak as: Astrid in "Swedish"
I can speak as: Vicki in "German"
I can speak as: Mia in "Mexican Spanish"
I can speak as: Bianca in "Italian"
I can speak as: Vitória in "Brazilian Portuguese"
I can speak as: Raveena in "Indian English"
I can speak as: Chantal in "Canadian French"
I can speak as: Amy in "British English"
I can speak as: Brian in "British English"
I can speak as: Kevin in "US English"
I can speak as: Russell in "Australian English"
I can speak as: Aditi in "Indian English"
I can speak as: Matthew in "US English"
I can speak as: Dóra in "Icelandic"
I can speak as: Enrique in "Castilian Spanish"
I can speak as: Hans in "German"
I can speak as: Carmen in "Romanian"
I can speak as: Ivy in "US English"
I can speak as: Ewa in "Polish"
I can speak as: Maja in "Polish"
I can speak as: Nicole in "Australian English"
I can speak as: Gabrielle in "Canadian French"
I can speak as: Camila in "Brazilian Portuguese"
I can speak as: Filiz in "Turkish"
I can speak as: Jacek in "Polish"
I can speak as: Justin in "US English"
I can speak as: Céline in "French"
I can speak as: Kendra in "US English"
I can speak as: Ricardo in "Brazilian Portuguese"
I can speak as: Mads in "Danish"
I can speak as: Mathieu in "French"
I can speak as: Léa in "French"
I can speak as: Naja in "Danish"
I can speak as: Penélope in "US Spanish"
I can speak as: Tatyana in "Russian"
I can speak as: Olivia in "Australian English"
I can speak as: Ruben in "Dutch"
I can speak as: Mizuki in "Japanese"
I can speak as: Takumi in "Japanese"
I can speak as: Conchita in "Castilian Spanish"
I can speak as: Carla in "Italian"
I can speak as: Kimberly in "US English"
I can speak as: Jan in "Polish"
I can speak as: Liv in "Norwegian"
I can speak as: Joey in "US English"
I can speak as: Lupe in "US Spanish"
I can speak as: Seoyeon in "Korean"
I can speak as: Emma in "British English"
Voices supporting a neural engine: [Salli, Joanna, Vicki, Amy, Brian, Kevin, Matthew, Ivy, Unknown("Gabrielle"), Camila, Justin, Kendra, Olivia, Kimberly, Joey, Lupe, Seoyeon, Emma]
test tts::tests::test_describe ... ok
まずお試し。いい感じ。
![tkt](https://res.cloudinary.com/zenn/image/fetch/s--xyLm7jsv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/300d20d9e5.jpeg)
Rust 1.49 だかでやってるとエラーが出て、1.51 くらいに上げると改善した
参考![tkt](https://res.cloudinary.com/zenn/image/fetch/s--xyLm7jsv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/300d20d9e5.jpeg)
実行はこのあたり
![tkt](https://res.cloudinary.com/zenn/image/fetch/s--xyLm7jsv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/300d20d9e5.jpeg)
環境変数で鍵を渡してる
![tkt](https://res.cloudinary.com/zenn/image/fetch/s--xyLm7jsv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/300d20d9e5.jpeg)
実行したのはこれ
![tkt](https://res.cloudinary.com/zenn/image/fetch/s--xyLm7jsv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/300d20d9e5.jpeg)
つぎこれ。再生ファイル生成できそう
![tkt](https://res.cloudinary.com/zenn/image/fetch/s--xyLm7jsv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/300d20d9e5.jpeg)
#[derive(Debug, StructOpt)]
struct Opt {
/// The region
#[structopt(short, long)]
region: Option<String>,
/// The file containing the text to synthesize
#[structopt(short, long)]
filename: String,
/// Whether to show additional output
#[structopt(short, long)]
verbose: bool,
}
このあたりとか、CLI用に調整されてたり、ファイルから読むようになってたりするので調整する
![tkt](https://res.cloudinary.com/zenn/image/fetch/s--xyLm7jsv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/300d20d9e5.jpeg)
CLI で実行して先に確認したほうが良いのではと思ったけど、動きそうなのでこのまま進める
![tkt](https://res.cloudinary.com/zenn/image/fetch/s--xyLm7jsv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/300d20d9e5.jpeg)
mp3 のダウンロードに成功
![tkt](https://res.cloudinary.com/zenn/image/fetch/s--xyLm7jsv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/300d20d9e5.jpeg)
SubscriberBuilder::default()
.with_env_filter("info")
.with_span_events(FmtSpan::CLOSE)
.init();
これを複数回呼び出すと
thread 'tokio-runtime-worker' panicked at 'Unable to install global subscriber: SetGlobalDefaultError { _no_construct: () }', /usr/local/cargo/registry/src/github.com-1ecc6299db9ec823/tracing-subscriber-0.2.18/src/fmt/mod.rs:571:14
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
怒られるので、singletonにするとかの対策をしないといけなそう
ただ実行するだけなら使わなくても大丈夫
![tkt](https://res.cloudinary.com/zenn/image/fetch/s--xyLm7jsv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/300d20d9e5.jpeg)
ローカルで動いた
![tkt](https://res.cloudinary.com/zenn/image/fetch/s--xyLm7jsv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/300d20d9e5.jpeg)
ローカルで動いた
![tkt](https://res.cloudinary.com/zenn/image/fetch/s--xyLm7jsv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/300d20d9e5.jpeg)
herokuに上げる
$ heroku login
$ heroku container:login
$ heroku create [<APPLICATION NAME>]
$ heroku config:set 環境変数
$ heroku stack:set container
$ heroku ps:scale worker=1
このあたりで動くようになった?
![tkt](https://res.cloudinary.com/zenn/image/fetch/s--xyLm7jsv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/300d20d9e5.jpeg)
まだ動くところまでは見えてないので様子見
2021-06-26T11:07:04.190523+00:00 app[app.1]: Compiling universal-hash v0.4.0
2021-06-26T11:07:04.272565+00:00 app[app.1]: Compiling aead v0.3.2
2021-06-26T11:07:05.289393+00:00 heroku[app.1]: Process running mem=614M(116.2%)
2021-06-26T11:07:05.291635+00:00 heroku[app.1]: Error R14 (Memory quota exceeded)
2021-06-26T11:07:06.876697+00:00 app[app.1]: Compiling syntex_syntax v0.42.0
2021-06-26T11:07:08.434419+00:00 app[app.1]: Compiling url v2.2.2
2021-06-26T11:07:08.438687+00:00 app[app.1]: Compiling rand_chacha v0.3.1
2021-06-26T11:07:20.802917+00:00 app[app.1]: Compiling rand_chacha v0.2.2
2021-06-26T11:07:24.604586+00:00 app[app.1]: Compiling audiopus v0.2.0
2021-06-26T11:07:26.418395+00:00 app[app.1]: Compiling webpki v0.21.4
2021-06-26T11:07:27.570347+00:00 app[app.1]: Compiling sct v0.6.1
2021-06-26T11:07:28.299319+00:00 app[app.1]: Compiling aws-types v0.1.0 (https://github.com/awslabs/aws-sdk-rust?tag=v0.0.7-alpha#1b923f86)
2021-06-26T11:07:29.876635+00:00 app[app.1]: Compiling enum_primitive v0.1.1
2021-06-26T11:07:30.837048+00:00 app[app.1]: Compiling sha-1 v0.9.6
2021-06-26T11:07:31.236532+00:00 app[app.1]: Compiling salsa20 v0.7.2
2021-06-26T11:07:31.411752+00:00 app[app.1]: Compiling poly1305 v0.6.2
2021-06-26T11:07:31.988065+00:00 heroku[app.1]: Process running mem=807M(151.9%)
2021-06-26T11:07:31.990173+00:00 heroku[app.1]: Error R14 (Memory quota exceeded)
2021-06-26T11:07:33.580496+00:00 app[app.1]: Compiling rand v0.8.4
2021-06-26T11:07:35.593107+00:00 app[app.1]: Compiling rand v0.7.3
2021-06-26T11:07:37.151300+00:00 app[app.1]: Compiling webpki-roots v0.21.1
2021-06-26T11:07:38.164274+00:00 app[app.1]: Compiling webpki-roots v0.20.0
2021-06-26T11:07:39.412978+00:00 app[app.1]: Compiling rustls v0.19.1
2021-06-26T11:07:41.941184+00:00 app[app.1]: Compiling ct-logs v0.8.0
2021-06-26T11:07:43.352893+00:00 app[app.1]: Compiling xsalsa20poly1305 v0.6.0
2021-06-26T11:07:44.047019+00:00 app[app.1]: Compiling tungstenite v0.11.1
2021-06-26T11:07:53.310837+00:00 heroku[app.1]: Process running mem=736M(138.0%)
2021-06-26T11:07:53.312790+00:00 heroku[app.1]: Error R14 (Memory quota exceeded
メモリが悲鳴を上げている
![tkt](https://res.cloudinary.com/zenn/image/fetch/s--xyLm7jsv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/300d20d9e5.jpeg)
021-06-26T11:09:00.122097+00:00 app[app.1]: Compiling syntex v0.42.2
2021-06-26T11:09:00.506887+00:00 heroku[app.1]: Process running mem=1072M(207.2%)
2021-06-26T11:09:00.508660+00:00 heroku[app.1]: Error R15 (Memory quota vastly exceeded)
2021-06-26T11:09:00.510568+00:00 heroku[app.1]: Stopping process with SIGKILL
2021-06-26T11:09:00.781304+00:00 heroku[app.1]: Process exited with status 0
2021-06-26T11:09:00.901447+00:00 heroku[app.1]: State changed from up to crashed
2021-06-26T11:09:00.917995+00:00 heroku[app.1]: State changed from crashed to starting
2021-06-26T11:09:24.385858+00:00 heroku[app.1]: Starting process with command `/bin/sh -c cargo\ run`
2021-06-26T11:09:25.156783+00:00 heroku[app.1]: State changed from starting to up
2021-06-26T11:09:29.425477+00:00 app[app.1]: Updating git repository `https://github.com/awslabs/aws-sdk-rust`
限界?
![tkt](https://res.cloudinary.com/zenn/image/fetch/s--xyLm7jsv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/300d20d9e5.jpeg)
2021-06-26T11:09:00.122097+00:00 app[app.1]: Compiling syntex v0.42.2
2021-06-26T11:09:00.506887+00:00 heroku[app.1]: Process running mem=1072M(207.2%)
2021-06-26T11:09:00.508660+00:00 heroku[app.1]: Error R15 (Memory quota vastly exceeded)
2021-06-26T11:09:00.510568+00:00 heroku[app.1]: Stopping process with SIGKILL
2021-06-26T11:09:00.781304+00:00 heroku[app.1]: Process exited with status 0
2021-06-26T11:09:00.901447+00:00 heroku[app.1]: State changed from up to crashed
2021-06-26T11:09:00.917995+00:00 heroku[app.1]: State changed from crashed to starting
2021-06-26T11:09:24.385858+00:00 heroku[app.1]: Starting process with command `/bin/sh -c cargo\ run`
2021-06-26T11:09:25.156783+00:00 heroku[app.1]: State changed from starting to up
2021-06-26T11:09:29.425477+00:00 app[app.1]: Updating git repository `https://github.com/awslabs/aws-sdk-rust`
2021-06-26T11:09:33.123622+00:00 app[app.1]: Updating crates.io index
2021-06-26T11:10:13.639242+00:00 app[app.1]: Updating git repository `https://github.com/rcoh/sigv4`
2021-06-26T11:10:14.121754+00:00 app[app.1]: Downloading crates ...
2021-06-26T11:10:14.332188+00:00 app[app.1]: Downloaded base64 v0.12.3
2021-06-26T11:10:14.347448+00:00 app[app.1]: Downloaded audiopus v0.2.0
2021-06-26T11:10:14.358910+00:00 app[app.1]: Downloaded async-tungstenite v0.13.1
2021-06-26T11:10:14.376605+00:00 app[app.1]: Downloaded pretty_assertions v0.7.2
2021-06-26T11:10:14.386350+00:00 app[app.1]: Downloaded proc-macro2 v1.0.27
2021-06-26T11:10:14.394338+00:00 app[app.1]: Downloaded quote v1.0.9
再始動してからは元気っぽい
![tkt](https://res.cloudinary.com/zenn/image/fetch/s--xyLm7jsv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/300d20d9e5.jpeg)
メモリエラー出だした
![tkt](https://res.cloudinary.com/zenn/image/fetch/s--xyLm7jsv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/300d20d9e5.jpeg)
コンパイルはイメージ作るときにやるべきか、
![tkt](https://res.cloudinary.com/zenn/image/fetch/s--xyLm7jsv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/300d20d9e5.jpeg)
Dockerfile 修正してから
heroku container:push app -a <APPLICATION NAME>
heroku container:release app -a <APPLICATION NAME>
heroku ps:scale app=1 -a <APPLICATION NAME>
![tkt](https://res.cloudinary.com/zenn/image/fetch/s--xyLm7jsv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/300d20d9e5.jpeg)
heroku logs --tail
これで起動時ログが見れた
![tkt](https://res.cloudinary.com/zenn/image/fetch/s--xyLm7jsv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/300d20d9e5.jpeg)
heroku コマンドも docker container 上でやってる
![tkt](https://res.cloudinary.com/zenn/image/fetch/s--xyLm7jsv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/300d20d9e5.jpeg)
version: "3.7"
services:
app:
build:
context: .
dockerfile: ./Dockerfile
# target: build-env
working_dir: /workspace
environment:
- USER=$USER
- DISCORD_TOKEN=$DISCORD_TOKEN
- AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID
- AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY
- AWS_REGION=$AWS_REGION
volumes:
- .:/workspace:cached
- target:/workspace/target:cached
tty: true
heroku:
# run `apk add docker` before running heroku commands
image: sue445/heroku-cli
volumes:
- .:/workspace:cached
- /var/run/docker.sock:/var/run/docker.sock:rw
volumes:
target:
FROM rust:1.53-slim-buster AS build-env
RUN apt-get update && \
apt-get install -y \
libopus-dev \
build-essential \
libssl-dev \
pkg-config \
autoconf \
automake \
libtool \
m4 \
ffmpeg \
curl \
python \
&& apt-get -y clean \
&& rm -rf /var/lib/apt/lists/*
RUN curl -L https://yt-dl.org/downloads/latest/youtube-dl -o /usr/bin/youtube-dl && \
chmod a+rx /usr/bin/youtube-dl
ENV LC_ALL=C.UTF-8
COPY Cargo.lock Cargo.lock
COPY Cargo.toml Cargo.toml
COPY . .
RUN cargo build --release
FROM debian:buster-20210621-slim
RUN apt-get update && \
apt-get install -y \
libopus-dev \
build-essential \
libssl-dev \
pkg-config \
autoconf \
automake \
libtool \
m4 \
ffmpeg \
curl \
python \
&& apt-get -y clean \
&& rm -rf /var/lib/apt/lists/*
RUN curl -L https://yt-dl.org/downloads/latest/youtube-dl -o /usr/bin/youtube-dl && \
chmod a+rx /usr/bin/youtube-dl
ENV LC_ALL=C.UTF-8
COPY /target/release/app /bin/app
CMD [ "/bin/sh", "-c", "app" ]
build stage のインストールもう少し削れそう
![tkt](https://res.cloudinary.com/zenn/image/fetch/s--xyLm7jsv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/300d20d9e5.jpeg)
2021-06-26T12:46:22.972828+00:00 app[app.1]: thread 'tokio-runtime-worker' panicked at 'failed to create file: Os { code: 2, kind: NotFound, message: "No such file or directory" }', src/tts/mod.rs:75:10
2021-06-26T12:46:31.586284+00:00 app[app.1]: thread 'tokio-runtime-worker' panicked at 'failed to create file: Os { code: 2, kind: NotFound, message: "No such file or directory" }', src/tts/mod.rs:75:10
2021-06-26T12:46:34.149492+00:00 app[app.1]: thread 'tokio-runtime-worker' panicked at 'failed to create file: Os { code: 2, kind: NotFound, message: "No such file or directory" }', src/tts/mod.rs:75:10
2021-06-26T12:47:01.890048+00:00 app[app.1]: thread 'tokio-runtime-worker' panicked at 'failed to create file: Os { code: 2, kind: NotFound, message: "No such file or directory" }', src/tts/mod.rs:75:10
panic してた。
let root = env!("CARGO_MANIFEST_DIR");
let path = Path::new(root);
このあたりが原因な気がする
![tkt](https://res.cloudinary.com/zenn/image/fetch/s--xyLm7jsv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/300d20d9e5.jpeg)
let root = env!("CARGO_MANIFEST_DIR");
println!("CARGO_MANIFEST_DIR: {}", root);
let path = Path::new(root);
println!("path: {}", path.display());
let file_path = path.join("binaries").join("tts");
println!("file_path: {}", file_path.display());
CARGO_MANIFEST_DIR: /
path: /
file_path: /binaries/tts
![tkt](https://res.cloudinary.com/zenn/image/fetch/s--xyLm7jsv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/300d20d9e5.jpeg)
tokio::fs::File::create
これではディレクトリの作成はやってくれないらしく、存在しない dir を渡すと
Os { code: 2, kind: NotFound, message: "No such file or directory" }
と怒られる
![tkt](https://res.cloudinary.com/zenn/image/fetch/s--xyLm7jsv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/300d20d9e5.jpeg)
Dockerfile でディレクトリを作っておく
![tkt](https://res.cloudinary.com/zenn/image/fetch/s--xyLm7jsv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/300d20d9e5.jpeg)
通った
![tkt](https://res.cloudinary.com/zenn/image/fetch/s--xyLm7jsv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/300d20d9e5.jpeg)
heroku にあげなおした
けど、しゃべらない
エラーログもでてない
![tkt](https://res.cloudinary.com/zenn/image/fetch/s--xyLm7jsv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/300d20d9e5.jpeg)
これは謎
![tkt](https://res.cloudinary.com/zenn/image/fetch/s--xyLm7jsv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/300d20d9e5.jpeg)
cargo run
でも喋らなくなってた
でぐれ?
![tkt](https://res.cloudinary.com/zenn/image/fetch/s--xyLm7jsv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/300d20d9e5.jpeg)
test は通る
そんなに数書いてないけど
![tkt](https://res.cloudinary.com/zenn/image/fetch/s--xyLm7jsv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/300d20d9e5.jpeg)
デバッグしてるサーバー変えてbotの権限が変わったのが問題かも
![tkt](https://res.cloudinary.com/zenn/image/fetch/s--xyLm7jsv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/300d20d9e5.jpeg)
dekita-
![tkt](https://res.cloudinary.com/zenn/image/fetch/s--xyLm7jsv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/300d20d9e5.jpeg)
だめだったサーバーでも再招待で動くようになった
![tkt](https://res.cloudinary.com/zenn/image/fetch/s--xyLm7jsv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/300d20d9e5.jpeg)
二回目以降の heroku 操作
docker-compose run --rm heroku /bin/bash
heroku login
apk add docker
heroku container:login
heroku container:push app -a <APP_NAME>
heroku container:release app -a <APP_NAME>
heroku ps:scale app=1 -a <APP_NAME>
![tkt](https://res.cloudinary.com/zenn/image/fetch/s--xyLm7jsv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/300d20d9e5.jpeg)
// 声質の変更と最大再生秒数の設定
// https://docs.aws.amazon.com/ja_jp/polly/latest/dg/supportedtags.html
ssml_text.push_str("<speak><prosody pitch=\"+200%\"><amazon:effect phonation=\"soft\"><amazon:effect vocal-tract-length=\"-15%\"><prosody amazon:max-duration=\"5s\">");
ssml_text.push_str(&content);
ssml_text.push_str("</prosody></amazon:effect></amazon:effect></prosody></speak>");
![tkt](https://res.cloudinary.com/zenn/image/fetch/s--xyLm7jsv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/300d20d9e5.jpeg)
一旦できたのでClose
![tkt](https://res.cloudinary.com/zenn/image/fetch/s--xyLm7jsv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/300d20d9e5.jpeg)
terraform の環境使わなくなったから別で書いといた
![tkt](https://res.cloudinary.com/zenn/image/fetch/s--xyLm7jsv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/300d20d9e5.jpeg)
今やるならこの機構をもとにやれば楽そう
![tkt](https://res.cloudinary.com/zenn/image/fetch/s--xyLm7jsv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_70/https://storage.googleapis.com/zenn-user-upload/avatar/300d20d9e5.jpeg)
スラッシュコマンド対応とかなんやかんやでまたたくさんcommitしてる