Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
YOUTUBE_API_KEY=your_youtube_api_key

# 以下の変数はローカル開発では設定不要です。
# docker-compose.yml のデフォルト値を上書きしたい場合のみ使用

# NS_MARIADB_HOSTNAME=db
# NS_MARIADB_PORT=3306
# NS_MARIADB_DATABASE=playbacq
# NS_MARIADB_USER=playbacq_user
# NS_MARIADB_PASSWORD=my_secure_password_123
# MYSQL_ROOT_PASSWORD=super_secret_root

# REDIS_HOST=redis
# REDIS_PORT=6379
# REDIS_USER=default
# REDIS_PASSWORD=

# MINIO_ROOT_USER=admin
# MINIO_ROOT_PASSWORD=super_secret_minio
# MINIO_ENDPOINT=minio:9000
# S3_ENDPOINT=http://127.0.0.1:9000

# FRONTEND_URL=http://localhost:4200
# BACKEND_URL=http://backend:8080

# LOCAL_WORKER_EXECUTABLE=./build/playbacq_worker
# LOCAL_BUILD_JOBS=6
# LOCAL_START_TIMEOUT=600
16 changes: 14 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ option(BUILD_BACKEND "Build the backend executable" ON)
option(BUILD_WORKER "Build the worker executable" ON)
option(BUILD_LOCAL_DEV "Build for local development with MinIO" OFF)
option(USE_LOCAL_WORKER "Use local worker for encoding" OFF)
option(USE_LOCAL_GPU_ENCODER "Use the NVIDIA GPU encoder for local development" OFF)

option(ENABLE_COVERAGE "Enable coverage reporting" OFF)
if(ENABLE_COVERAGE)
Expand Down Expand Up @@ -71,8 +72,12 @@ if(BUILD_WORKER)
if(BUILD_LOCAL_DEV)
target_compile_definitions(playbacq_worker PRIVATE USE_INTERNAL_S3)
endif()
if(USE_LOCAL_WORKER)
target_compile_definitions(playbacq_worker PRIVATE USE_LOCAL_WORKER)

if(NOT BUILD_LOCAL_DEV OR USE_LOCAL_GPU_ENCODER)
target_compile_definitions(playbacq_worker PRIVATE USE_NVIDIA_ENCODER)
message(STATUS "Worker Encoder: GPU (h264_nvenc)")
else()
message(STATUS "Worker Encoder: CPU (libx264)")
endif()
message(STATUS "Configured to build: WORKER")
endif()
Expand Down Expand Up @@ -112,6 +117,13 @@ if(BUILD_BACKEND)
${CMAKE_CURRENT_SOURCE_DIR}/plugins
)

if(USE_LOCAL_WORKER)
find_package(Boost REQUIRED COMPONENTS filesystem)
target_link_libraries(playbacq_core PUBLIC Boost::filesystem)
target_compile_definitions(playbacq_core PRIVATE USE_LOCAL_WORKER)
message(STATUS "Worker Dispatch: LOCAL")
endif()

add_executable(${PROJECT_NAME} main.cpp)
target_compile_options(${PROJECT_NAME} PRIVATE
-Wall -Wextra -Wpedantic -O3
Expand Down
11 changes: 7 additions & 4 deletions Dockerfile.dev
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
FROM unabc/playbacq-base:v2 AS builder
FROM unabc/playbacq-base:v2 AS development
# キャッシュバスター
ENV FORCE_REBUILD_CACHE_BUST=1
RUN ldconfig
ARG BUILD_JOBS=12
WORKDIR /app

FROM development AS builder
ARG BUILD_JOBS=12
COPY CMakeLists.txt /app/
COPY *.cpp /app/

Expand All @@ -14,7 +16,7 @@ COPY plugins/ /app/plugins/
COPY worker/ /app/worker/
COPY config.json config.yaml /app/

RUN mkdir build && cd build && cmake .. -DBUILD_LOCAL_DEV=ON && make -j${BUILD_JOBS}
RUN mkdir build && cd build && cmake .. -DBUILD_LOCAL_DEV=ON -DUSE_LOCAL_WORKER=ON && make -j${BUILD_JOBS}

FROM gcc:15.2
ENV DEBIAN_FRONTEND=noninteractive
Expand All @@ -33,6 +35,7 @@ COPY --from=builder /usr/lib/x86_64-linux-gnu/libboost_*.so* /usr/lib/x86_64-lin
RUN ldconfig

WORKDIR /app
ENV LOCAL_WORKER_EXECUTABLE=/usr/local/bin/playbacq_worker
COPY config.json config.yaml /app/

COPY --from=builder /app/build/playbacq /usr/local/bin/playbacq
Expand All @@ -41,4 +44,4 @@ COPY --from=builder /app/build/playbacq_worker /usr/local/bin/playbacq_worker
RUN chmod +x /usr/local/bin/playbacq_worker

EXPOSE 8080
CMD ["/usr/local/bin/playbacq"]
CMD ["/usr/local/bin/playbacq"]
25 changes: 25 additions & 0 deletions GNUmakefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
LOCAL_COMPOSE = docker compose -f docker-compose.yml -f docker-compose.local.yml
LOCAL_GPU_COMPOSE = $(LOCAL_COMPOSE) -f docker-compose.local-gpu.yml

.PHONY: local-dev local-dev-gpu local-dev-status local-dev-logs local-dev-shell local-dev-down

local-dev:
$(LOCAL_COMPOSE) up -d --build --force-recreate backend
$(LOCAL_COMPOSE) exec -T backend /bin/sh /app/docker/dev/wait-ready.sh

local-dev-gpu:
$(LOCAL_GPU_COMPOSE) up -d --build --force-recreate backend
$(LOCAL_GPU_COMPOSE) exec -T backend /bin/sh /app/docker/dev/wait-ready.sh

local-dev-status:
$(LOCAL_COMPOSE) ps -a
@$(LOCAL_COMPOSE) exec -T backend /bin/sh /app/docker/dev/status.sh

local-dev-logs:
$(LOCAL_COMPOSE) logs -f backend

local-dev-shell:
$(LOCAL_COMPOSE) exec backend bash

local-dev-down:
$(LOCAL_COMPOSE) down
100 changes: 97 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,11 @@
* **Others**: AWS SDK for C++ (S3 Plugin)

## 環境構築
`
```
docker compose up -d
`
```

`.env`は`.env.example`を参考に設定

## 実行
```
Expand All @@ -30,7 +32,99 @@ cmake ..
make
./playbacq
```

または

VSCodeでCMake Toolsを使用してビルド+実行。

## ローカル

### `make local-dev`

次のコマンドで、ローカル環境のビルドから起動までまとめて実行可能です。

```bash
make local-dev
```

内部では次の処理を行います。

1. MySQL、Redis、MinIO、バックエンドコンテナを起動
2. `BUILD_LOCAL_DEV=ON`と`USE_LOCAL_WORKER=ON`でCMake configure
3. `build`が未作成なら通常ビルド、作成済みならインクリメンタルビルド
4. `./build/playbacq`を起動
5. バックエンドの8080番ポートが利用可能になるまで待機

エンコードにはCPUを使用します。GPUを使用する場合は補助コマンドを利用する。

### 手動

開発用コンテナを起動して手動でビルド・実行することもできます。

```bash
docker compose up -d
docker compose exec backend bash
```

コンテナ内で実行

```bash
cmake -S . -B build -DBUILD_LOCAL_DEV=ON -DUSE_LOCAL_WORKER=ON
cmake --build build -j$(nproc)
./build/playbacq
```

#### VSCode CMake Tools

VSCodeのCmake Toolsでもビルド・実行可能です。

CMake Toolsには次を設定します。

```json
{
"cmake.buildDirectory": "${workspaceFolder}/build",
"cmake.configureSettings": {
"CMAKE_BUILD_TYPE": "Debug",
"BUILD_LOCAL_DEV": "ON",
"USE_LOCAL_WORKER": "ON"
},
"cmake.buildBeforeRun": true,
"cmake.debugConfig": {
"cwd": "${workspaceFolder}"
}
}
```

ビルドターゲットは`all`、実行・デバッグ対象は`playbacq`を選択します。
CMake Toolsから実行する場合は`make local-dev`を実行せず`docker compose up -d`を実行。

### 補助コマンド

サービスの稼働状況、ローカルCPU/GPUモード、エンコーダー設定を表示します。

```bash
make local-dev-status
```

バックエンドのログを表示します。

```bash
make local-dev-logs
```

開発用コンテナのシェルを開きます。

```bash
make local-dev-shell
```

ローカル環境を停止します。

```bash
make local-dev-down
```

ローカルでもNVIDIA GPUを使用してエンコードする場合は、次のコマンドを使用します。

```bash
make local-dev-gpu
```
25 changes: 22 additions & 3 deletions controllers/webhooks_minio.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
#include <drogon/orm/Criteria.h>
#include <json/json.h>
#include <boost/process.hpp>
#include <cstdlib>
#include <filesystem>
#include <stdexcept>
#include <thread>
#include "../models/Videos.h"
#include "Status.h"
Expand Down Expand Up @@ -56,11 +59,27 @@ drogon::Task<drogon::HttpResponsePtr> minio::asyncHandleHttpRequest(HttpRequestP
auto video = co_await mapper.findByPrimaryKey(videoId);
video.setStatus((uint8_t)Status::processing);
co_await mapper.update(video);
std::cout << "Pushing video ID " << videoId << " to Modal" << std::endl;
std::cout << "Dispatching video ID " << videoId << " for encoding" << std::endl;
#ifdef USE_LOCAL_WORKER
std::thread([videoId]() {
try {
boost::process::child c("./build/playbacq_worker", videoId);
const char* workerExecutableEnv = std::getenv("LOCAL_WORKER_EXECUTABLE");
const std::string workerExecutable = workerExecutableEnv
? workerExecutableEnv
: "./build/playbacq_worker";
std::string resolvedWorkerExecutable = workerExecutable;
if (!std::filesystem::exists(resolvedWorkerExecutable)) {
const auto workerPath = boost::process::search_path(workerExecutable);
if (!workerPath.empty()) {
resolvedWorkerExecutable = workerPath.string();
}
}
if (!std::filesystem::exists(resolvedWorkerExecutable)) {
throw std::runtime_error("Local worker executable not found: " + workerExecutable);
}
std::cout << "Starting local worker " << resolvedWorkerExecutable
<< " for video ID " << videoId << std::endl;
boost::process::child c(resolvedWorkerExecutable, videoId);
c.detach();
}
catch (const std::exception& e) {
Expand Down Expand Up @@ -154,4 +173,4 @@ drogon::Task<drogon::HttpResponsePtr> minio::receiveEncodeResult(HttpRequestPtr
auto resp = drogon::HttpResponse::newHttpResponse();
resp->setStatusCode(drogon::HttpStatusCode::k200OK);
co_return resp;
}
}
6 changes: 6 additions & 0 deletions docker-compose.local-gpu.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
services:
backend:
gpus: all
environment:
LOCAL_GPU_ENCODER: "ON"
NVIDIA_DRIVER_CAPABILITIES: compute,video,utility
8 changes: 8 additions & 0 deletions docker-compose.local.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
services:
backend:
build:
target: development
command: ["/bin/sh", "/app/docker/dev/start.sh"]
environment:
LOCAL_BUILD_JOBS: ${LOCAL_BUILD_JOBS:-6}
LOCAL_START_TIMEOUT: ${LOCAL_START_TIMEOUT:-600}
Loading
Loading