Closed113

discord で読み上げ bot をつくる

tkttkt

example 作れたけど、これはどうやったら動かせるんだ?

tkttkt

local serve して、/ping 投げても帰ってこない

tkttkt

さっき動かなかったのは、コマンドが違った説

tkttkt
.configure(|c| c.prefix("~")) // set the bot's prefix to "~"

これで設定してた。

ので、コマンドは ~ping

tkttkt

start で読み取り開始して voice に入室。
それ以降はメッセージの追加を検知して読み取る必要がある。
できるかな、

tkttkt

webhook とか設定してないけど、どうやって動いてるのか…

tkttkt

このライブラリだと、ボイスチャット系に対応してないかも?

tkttkt

そのようなライブラリの1つがSerenityです。これは、オプションを利用できるようにしながら、心配する必要のないものを抽象化するライブラリです。これはDiscordAPIをラップアラウンドし、音声サポートとすべての作業を備えた、ほとんど機能が完全です。

https://ichi.pro/rust-de-discord-botto-o-sakuseisuru-hoho-49539503791972

気づいてないだけかも

tkttkt

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)
tkttkt
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

それでもだめだった

tkttkt

intel mac に切り替えて作業することにする

tkttkt

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

依存してる何かが入ってない?

tkttkt
/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]

どういうこっちゃ

tkttkt
/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 したら落ちた。まだいろいろいるのかも

tkttkt
RUN apk update && \
    apk upgrade && \
    apk add --update --no-cache alpine-sdk git opus-dev build-base autoconf automake libtool m4 ffmpeg

これだけ入れてもだめっぽい

tkttkt

alpine だとダメかもなので ubuntu のイメージ引っ張ってくる

tkttkt
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" ]

これでもだめだった

tkttkt

Voiceのとこが動かんかったので、次は再生のexampleそのままとってきてちゃれんじ

tkttkt

youtube の音流すのはできたので

  • message 読み取り
  • 音声変換
  • lambda に乗せてみる
tkttkt

lambda には果たして乗るのだろうか

tkttkt

ローカルで動かして、youtube の url いれたら音が流れるようにはなった

tkttkt

ローカルで動かして、youtube の url いれたら音が流れるようにはなった

tkttkt

今回は音声ファイルを取得してきてそれを流したいけど、やり方がよくわからない

tkttkt
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 を作れば流せるみたいだけど、それを作ってるのが独自手法過ぎて(?)よくわからん

tkttkt

ローカルファイルからinputを作る方法で簡単なのがないか探す

tkttkt
// 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 多めだしなんとかなりそう…?

tkttkt

metadata 見てると曲であること前提の構造に見えて、喋らせたいとかの場合これではないので貼って思えてきた

tkttkt

https://docs.rs/songbird/0.1.6/songbird/tracks/struct.Track.html

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.

それっぽいのがあった

tkttkt

とりあえずこれでローカルファイルが流せるかやってみる

tkttkt

ffmpeg とか youtube-dl とか使ってるのがメインだから、rust じゃなくていいのでは?
とか思っちゃったけど、今は考えてはいけない

tkttkt

https://docs.rs/songbird/0.1.6/songbird/struct.Call.html
これの play_only を呼び出したい
Methods from Deref<Target = Driver> これはどうやって呼び出すのか
Rust 力が足りない

tkttkt

ソースで定義見ると、ちゃんと impl されてる

tkttkt
/// 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 しないとだめ?

tkttkt

ソース追ってたらいつの間にか使えるようになってた
ロードできてなかっただけ?

tkttkt

handler.play(track);
だと再生できなかった
次は
handler.enque(track);
で試す

tkttkt

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
}

これでいけそう

tkttkt

handler.play(track);
だと再生できなかった
次は
handler.enque(track);
で試す

ファイルパスの指定が間違っていた可能性が大

tkttkt
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 で再生に成功

tkttkt
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

サンプル通そうとしてるけど、応答さえない

tkttkt

stars は少ないけど、 init が 2months ago でこれから伸びてきそう
こっちつかってみる

tkttkt
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

まずお試し。いい感じ。

tkttkt
#[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用に調整されてたり、ファイルから読むようになってたりするので調整する

tkttkt

CLI で実行して先に確認したほうが良いのではと思ったけど、動きそうなのでこのまま進める

tkttkt
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にするとかの対策をしないといけなそう
ただ実行するだけなら使わなくても大丈夫

tkttkt

herokuに上げる

$ heroku login
$ heroku container:login
$ heroku create [<APPLICATION NAME>]
$ heroku config:set 環境変数
$ heroku stack:set container
$ heroku ps:scale worker=1

このあたりで動くようになった?

tkttkt

まだ動くところまでは見えてないので様子見

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

メモリが悲鳴を上げている

tkttkt
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`

限界?

tkttkt
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

再始動してからは元気っぽい

tkttkt

コンパイルはイメージ作るときにやるべきか、

tkttkt

Dockerfile 修正してから

heroku container:push app -a <APPLICATION NAME>
heroku container:release app -a <APPLICATION NAME>
heroku ps:scale app=1 -a <APPLICATION NAME>
tkttkt
heroku logs --tail

これで起動時ログが見れた

tkttkt

heroku コマンドも docker container 上でやってる

tkttkt
docker-compose.yml
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 --from=build-env /target/release/app /bin/app

CMD [ "/bin/sh",  "-c", "app" ]

build stage のインストールもう少し削れそう

tkttkt
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);

このあたりが原因な気がする

tkttkt
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
tkttkt
tokio::fs::File::create

これではディレクトリの作成はやってくれないらしく、存在しない dir を渡すと

Os { code: 2, kind: NotFound, message: "No such file or directory" }

と怒られる

tkttkt

Dockerfile でディレクトリを作っておく

tkttkt

heroku にあげなおした
けど、しゃべらない
エラーログもでてない

tkttkt

cargo run でも喋らなくなってた
でぐれ?

tkttkt

test は通る
そんなに数書いてないけど

tkttkt

デバッグしてるサーバー変えてbotの権限が変わったのが問題かも

tkttkt

だめだったサーバーでも再招待で動くようになった

tkttkt

二回目以降の 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>
tkttkt
// 声質の変更と最大再生秒数の設定
// 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>");
tkttkt

スラッシュコマンド対応とかなんやかんやでまたたくさんcommitしてる

このスクラップは2021/06/27にクローズされました