197 lines
7.4 KiB
Markdown
197 lines
7.4 KiB
Markdown
# 클라이언트 방향성
|
|
|
|
이 문서는 Orange Pi Zero 2W에서 실행할 마이크 송신기 클라이언트의 초기 방향을 정리합니다.
|
|
|
|
현재 단계의 목표는 복잡한 기능을 넣는 것이 아니라, USB 마이크 입력을 Mac 수신기까지 보내서 `소리가 나온다`는 것을 확인하는 것입니다.
|
|
|
|
## 역할
|
|
|
|
클라이언트는 Orange Pi Zero 2W에서 실행되며 다음 역할을 맡습니다.
|
|
|
|
- USB 마이크를 ALSA 오디오 입력 장치로 인식합니다.
|
|
- 마이크에서 캡처한 오디오 프레임을 네트워크 패킷으로 나눕니다.
|
|
- Wi-Fi 공유기를 통해 Mac 수신기/믹서로 오디오를 전송합니다.
|
|
- 통신 문제에 대비해 같은 캡처 오디오를 로컬 WAV 파일로 저장합니다.
|
|
- 초기 버전에서는 송신기 1대만 검증합니다.
|
|
|
|
```text
|
|
USB 마이크 -> Orange Pi Zero 2W 클라이언트 -> UDP/Wi-Fi -> Mac 수신기
|
|
```
|
|
|
|
## 초기 범위
|
|
|
|
초기 클라이언트의 성공 기준은 다음과 같습니다.
|
|
|
|
- Orange Pi Zero 2W가 정상 부팅되고 SSH로 접속됩니다.
|
|
- USB 마이크가 Linux ALSA 장치로 보입니다.
|
|
- 클라이언트가 마이크 입력을 캡처합니다.
|
|
- Mac 수신기가 클라이언트의 UDP 패킷을 받습니다.
|
|
- Mac에서 실제 오디오가 들립니다.
|
|
- Orange Pi 내부 저장장치에 로컬 백업 녹음본이 남습니다.
|
|
|
|
지연 시간 최적화, 다중 송신기, 자동 검색, 압축, 동기화, UI는 초기 성공 이후에 다룹니다.
|
|
|
|
## 마이크 기준
|
|
|
|
USB 라발리에 마이크 모델은 고정하지 않습니다.
|
|
|
|
첫 테스트는 MATA STUDIO C300 같은 일반 USB 마이크로 진행할 수 있습니다. 단, 마이크마다 지원 포맷이 다를 수 있으므로 클라이언트는 특정 모델이나 ALSA 카드 번호에 강하게 의존하지 않아야 합니다.
|
|
|
|
주의할 점은 다음과 같습니다.
|
|
|
|
- USB Audio Class 장치로 ALSA에서 인식되는지 확인해야 합니다.
|
|
- 마이크가 96 kHz/24-bit 같은 고해상도 포맷을 우선 지원할 수 있습니다.
|
|
- 초기 송신 포맷과 마이크의 실제 캡처 포맷이 다르면 ALSA `plug` 변환 또는 별도 변환이 필요할 수 있습니다.
|
|
- 마이크 자체의 MUTE, 게인, 볼륨 설정 때문에 캡처가 무음처럼 보일 수 있습니다.
|
|
- 여러 USB 오디오 장치가 연결되면 ALSA 카드 번호가 바뀔 수 있습니다.
|
|
|
|
## 오디오 캡처 방향
|
|
|
|
초기 오디오 캡처는 ALSA 기반으로 진행합니다.
|
|
|
|
초기 후보 포맷은 다음과 같습니다.
|
|
|
|
```text
|
|
sample_rate = 48000
|
|
sample_format = signed 16-bit little endian
|
|
channels = 1
|
|
frame_ms = 20
|
|
```
|
|
|
|
이 값은 구현 시작점일 뿐입니다. 실제 장치가 지원하지 않으면 44.1 kHz, 96 kHz, 24-bit 등으로 조정하거나 ALSA 변환 장치를 사용합니다.
|
|
|
|
ALSA 장치명은 설정 파일 또는 실행 옵션으로 지정할 수 있게 합니다.
|
|
|
|
예시:
|
|
|
|
```text
|
|
alsa_device = default
|
|
```
|
|
|
|
테스트 단계에서는 `arecord -l`, `arecord -L`로 장치 목록을 확인하고, 짧은 녹음 테스트로 실제 입력 여부를 확인합니다.
|
|
|
|
## 네트워크 전송 방향
|
|
|
|
초기 전송은 UDP 기반으로 진행합니다.
|
|
|
|
UDP를 우선 검토하는 이유는 다음과 같습니다.
|
|
|
|
- 오디오 스트리밍의 최소 경로를 빠르게 확인할 수 있습니다.
|
|
- TCP보다 지연과 재전송 정책이 단순합니다.
|
|
- 첫 목표가 완전한 품질보다 오디오 경로 검증이기 때문입니다.
|
|
|
|
현재 초기 구현은 간단한 헤더와 PCM payload로 UDP 패킷을 구성합니다.
|
|
|
|
헤더 형식:
|
|
|
|
```text
|
|
magic 4 bytes "MIC1"
|
|
version u16
|
|
header_size u16
|
|
sequence u64
|
|
timestamp_frames u64
|
|
sample_rate u32
|
|
channels u16
|
|
bits_per_sample u16
|
|
frame_count u32
|
|
payload_bytes u32
|
|
```
|
|
|
|
헤더 숫자 값은 network byte order로 전송합니다. PCM payload는 signed 16-bit little endian입니다.
|
|
|
|
서버 구현은 이 형식에 맞춰 수신 경로를 만들되, 실제 재생 테스트 중 문제가 있으면 클라이언트와 서버를 함께 조정합니다.
|
|
|
|
## 수신기 주소 설정
|
|
|
|
첫 버전은 Mac 수신기 IP를 설정 파일에서 지정하는 방향을 우선합니다.
|
|
|
|
자동 검색은 좋은 확장 기능이지만, 초기 오디오 경로 검증에서는 고정 설정이 더 단순하고 문제 원인을 분리하기 쉽습니다.
|
|
|
|
설정 파일 후보:
|
|
|
|
```text
|
|
server_host = 192.168.0.10
|
|
server_port = 4860
|
|
alsa_device = default
|
|
sample_rate = 48000
|
|
channels = 1
|
|
frame_ms = 20
|
|
record_enabled = true
|
|
record_dir = recordings
|
|
```
|
|
|
|
초기 버전의 `server_port`는 `4860`으로 정합니다.
|
|
|
|
작업 중 여러 포트가 필요해지면 `4800-5000` 범위 안에서 배정하는 방향으로 둡니다.
|
|
|
|
## 자동 검색 확장 후보
|
|
|
|
자동 검색은 초기 성공 이후 다음 방식으로 검토합니다.
|
|
|
|
- 클라이언트가 같은 서브넷에 UDP broadcast 또는 multicast 탐색 패킷을 보냅니다.
|
|
- Mac 수신기가 자신의 주소와 수신 포트를 응답합니다.
|
|
- 클라이언트는 응답받은 주소로 오디오 송신을 시작합니다.
|
|
|
|
공유기, 방화벽, 네트워크 분리 설정에 따라 자동 검색이 실패할 수 있으므로 고정 설정 파일 방식은 계속 유지합니다.
|
|
|
|
## 구현 후보
|
|
|
|
구현 언어는 C++입니다.
|
|
|
|
라이브러리와 도구 후보는 다음과 같습니다.
|
|
|
|
- 오디오 캡처: ALSA, `libasound2-dev`
|
|
- 네트워크: POSIX UDP socket
|
|
- 설정 파일: 단순 key-value 텍스트 형식
|
|
- 빌드: CMake 후보
|
|
|
|
현재 초기 클라이언트 구현은 `client/`에 있습니다.
|
|
|
|
- `client/src/main.cpp`: ALSA 캡처, UDP 송신, 로컬 WAV 백업 녹음
|
|
- `client/CMakeLists.txt`: CMake 빌드 구성
|
|
- `client/client.conf.example`: 설정 파일 예시
|
|
- `client/README.md`: 빌드와 실행 절차
|
|
|
|
## 로컬 백업 녹음 방향
|
|
|
|
클라이언트는 실행 중 Wi-Fi UDP 송신과 동시에 로컬 WAV 파일을 저장합니다.
|
|
|
|
초기 기준은 다음과 같습니다.
|
|
|
|
```text
|
|
record_enabled = true
|
|
record_dir = recordings
|
|
```
|
|
|
|
녹음 파일은 실행 위치 기준 `recordings/`에 생성합니다. 파일명은 녹음 시작 일자와 실행 시각을 사용합니다.
|
|
|
|
예시:
|
|
|
|
```text
|
|
recordings/mic-client-20260602-165000.wav
|
|
```
|
|
|
|
파일 분할은 하지 않습니다. 클라이언트가 재부팅 또는 재실행되면 새 파일을 만듭니다.
|
|
|
|
로컬 녹음은 방송 중 통신 문제로 음성이 깨졌을 때 후작업에 사용할 백업입니다. 따라서 녹음 파일 생성, 디렉터리 생성, 파일 쓰기, 종료 시 WAV 헤더 갱신에 실패해도 클라이언트 프로그램은 종료하지 않습니다. 이 경우 경고를 출력하고 로컬 저장 없이 Wi-Fi 송신을 계속합니다.
|
|
|
|
## 검증 순서
|
|
|
|
초기 검증은 다음 순서를 따릅니다.
|
|
|
|
1. Orange Pi Zero 2W OS 부팅 확인
|
|
2. SSH 접속 확인
|
|
3. Wi-Fi 연결 확인
|
|
4. USB 마이크 장치 인식 확인
|
|
5. ALSA 짧은 녹음 테스트 확인
|
|
6. Mac 수신기의 UDP 수신 확인
|
|
7. 클라이언트에서 단일 송신기 오디오 전송 확인
|
|
8. Mac에서 실제 오디오 출력 확인
|
|
9. Orange Pi의 `recordings/`에 WAV 백업 파일 생성 확인
|
|
|
|
## 다음 단계
|
|
|
|
다음 작업은 서버 방향성과 최소 UDP 수신 경로를 함께 정한 뒤, 클라이언트와 서버의 패킷 포맷을 맞추는 것입니다.
|
|
|
|
다음 작업은 Mac 서버가 현재 클라이언트의 UDP 패킷 형식을 수신하고 PCM payload를 재생할 수 있도록 맞추는 것입니다.
|