Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
6 changes: 6 additions & 0 deletions .github/actions/build-container/action.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ inputs:
skyeye-version:
description: 'Version to use in build args'
required: true
tag-suffix:
description: 'Suffix appended to image tags (e.g. -vulkan)'
required: false
default: ''
runs:
using: composite
steps:
Expand All @@ -35,6 +39,8 @@ runs:
uses: docker/metadata-action@v5
with:
images: ${{ inputs.registry }}/${{ inputs.image-name }}
flavor: |
suffix=${{ inputs.tag-suffix }},onlatest=true
- name: Build and push Docker image
id: push
uses: docker/build-push-action@v6
Expand Down
6 changes: 5 additions & 1 deletion .github/actions/build-whisper/action.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,13 @@ inputs:
description: 'The shell to use'
required: true
default: 'bash'
make-args:
description: 'Extra arguments passed to make (e.g. GGML_VULKAN=1)'
required: false
default: ''
runs:
using: composite
steps:
- name: Build whisper.cpp
shell: ${{ inputs.shell }}
run: make whisper
run: make whisper ${{ inputs.make-args }}
130 changes: 130 additions & 0 deletions .github/workflows/skyeye.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,117 @@ jobs:
path: dist/skyeye-windows-amd64.zip
if-no-files-found: error
overwrite: true
build-linux-amd64-vulkan:
name: Build on Linux AMD64 (Vulkan)
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Setup
uses: ./.github/actions/setup
- name: Build whisper.cpp
uses: ./.github/actions/build-whisper
with:
make-args: GGML_VULKAN=1
- name: Build SkyEye
run: make skyeye-vulkan
- name: Build SkyEye Scaler
run: make skyeye-scaler
- name: Smoke test
run: ./skyeye-vulkan --help
- name: Create dist
shell: bash
run: |
mkdir -p dist/skyeye-linux-amd64-vulkan/docs/
cp skyeye-vulkan dist/skyeye-linux-amd64-vulkan/skyeye
cp skyeye-scaler dist/skyeye-linux-amd64-vulkan/skyeye-scaler
chmod +x dist/skyeye-linux-amd64-vulkan/skyeye
chmod +x dist/skyeye-linux-amd64-vulkan/skyeye-scaler
cp README.md dist/skyeye-linux-amd64-vulkan/README.md
cp LICENSE dist/skyeye-linux-amd64-vulkan/LICENSE
cp config.yaml dist/skyeye-linux-amd64-vulkan/config.yaml
cp docs/*.md dist/skyeye-linux-amd64-vulkan/docs/
tar -czf dist/skyeye-linux-amd64-vulkan.tar.gz -C dist skyeye-linux-amd64-vulkan
- name: Upload artifact
if: startsWith(github.ref, 'refs/tags/')
uses: actions/upload-artifact@v5
with:
name: skyeye-linux-amd64-vulkan.tar.gz
path: dist/skyeye-linux-amd64-vulkan.tar.gz
if-no-files-found: error
overwrite: true
build-windows-amd64-vulkan:
name: Build on Windows AMD64 (Vulkan)
runs-on: windows-latest
permissions:
contents: read
env:
GOROOT: /ucrt64/lib/go
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Set up MSYS2
uses: msys2/setup-msys2@v2
with:
msystem: UCRT64
install: |
base-devel
git
mingw-w64-ucrt-x86_64-cmake
mingw-w64-ucrt-x86_64-gcc
mingw-w64-ucrt-x86_64-toolchain
mingw-w64-ucrt-x86_64-opus
mingw-w64-ucrt-x86_64-libsoxr
mingw-w64-ucrt-x86_64-gcc
mingw-w64-ucrt-x86_64-go
mingw-w64-ucrt-x86_64-curl
mingw-w64-ucrt-x86_64-vulkan-headers
mingw-w64-ucrt-x86_64-vulkan-loader
mingw-w64-ucrt-x86_64-shaderc
mingw-w64-ucrt-x86_64-spirv-headers
zip
- name: Build whisper.cpp
uses: ./.github/actions/build-whisper
with:
os: windows
shell: msys2 {0}
make-args: GGML_VULKAN=1
- name: Build Skyeye
shell: msys2 {0}
run: make skyeye-vulkan
- name: Build Skyeye Scaler
shell: msys2 {0}
run: make skyeye-scaler.exe
- name: Smoke test
shell: msys2 {0}
run: ./skyeye-vulkan.exe --help
- name: Create dist
shell: msys2 {0}
run: |
mkdir -p dist/skyeye-windows-amd64-vulkan/docs/
cp skyeye-vulkan.exe dist/skyeye-windows-amd64-vulkan/skyeye.exe
cp skyeye-scaler.exe dist/skyeye-windows-amd64-vulkan/skyeye-scaler.exe
curl -fsL https://github.com/winsw/winsw/releases/download/v2.12.0/WinSW-x64.exe -o winsw.exe
cp README.md dist/skyeye-windows-amd64-vulkan/README.md
cp LICENSE dist/skyeye-windows-amd64-vulkan/LICENSE
cp config.yaml dist/skyeye-windows-amd64-vulkan/config.yaml
cp docs/*.md dist/skyeye-windows-amd64-vulkan/docs/
cp winsw.exe dist/skyeye-windows-amd64-vulkan/skyeye-service.exe
cp init/winsw/skyeye-service.yml dist/skyeye-windows-amd64-vulkan/skyeye-service.yml
cp winsw.exe dist/skyeye-windows-amd64-vulkan/skyeye-scaler-service.exe
cp init/winsw/skyeye-scaler-service.yml dist/skyeye-windows-amd64-vulkan/skyeye-scaler-service.yml
cd dist
zip -r skyeye-windows-amd64-vulkan.zip skyeye-windows-amd64-vulkan
- name: Upload artifact
if: startsWith(github.ref, 'refs/tags/')
uses: actions/upload-artifact@v5
with:
name: skyeye-windows-amd64-vulkan.zip
path: dist/skyeye-windows-amd64-vulkan.zip
if-no-files-found: error
overwrite: true
build-image:
name: Build container image
if: "!startsWith(github.ref, 'refs/tags/')"
Expand All @@ -196,6 +307,12 @@ jobs:
with:
build-args: |
SKYEYE_VERSION: ${{ env.GITHUB_REF_NAME }}
- name: Build Vulkan image
uses: docker/build-push-action@v6
with:
build-args: |
SKYEYE_VERSION: ${{ env.GITHUB_REF_NAME }}
target: skyeye-vulkan
release:
name: Upload release assets
if: startsWith(github.ref, 'refs/tags/')
Expand All @@ -207,6 +324,8 @@ jobs:
- build-linux-amd64
- build-windows-amd64
- build-macos-arm64
- build-linux-amd64-vulkan
- build-windows-amd64-vulkan
runs-on: ubuntu-latest
steps:
- name: Checkout
Expand All @@ -224,6 +343,8 @@ jobs:
dist/skyeye-linux-amd64.tar.gz
dist/skyeye-macos-arm64.tar.gz
dist/skyeye-windows-amd64.zip
dist/skyeye-linux-amd64-vulkan.tar.gz
dist/skyeye-windows-amd64-vulkan.zip
token: ${{ secrets.RELEASE_TOKEN }}
push-images:
name: Build and push container images
Expand Down Expand Up @@ -256,3 +377,12 @@ jobs:
image-name: ${{ github.repository }}-scaler
target: skyeye-scaler
skyeye-version: ${{ env.GITHUB_REF_NAME }}
- name: Build and push Vulkan image
uses: ./.github/actions/build-container
with:
registry-username: ${{ github.actor }}
registry-password: ${{ secrets.GITHUB_TOKEN }}
image-name: ${{ github.repository }}
target: skyeye-vulkan
tag-suffix: -vulkan
skyeye-version: ${{ env.GITHUB_REF_NAME }}
22 changes: 21 additions & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ COPY pkg pkg
RUN make skyeye
RUN make skyeye-scaler

FROM debian:bookworm-slim AS base
FROM debian:trixie-slim AS base
RUN apt-get update && apt-get install -y \
ca-certificates \
libopus0 \
Expand All @@ -36,3 +36,23 @@ ENTRYPOINT ["/opt/skyeye/bin/skyeye"]
FROM base AS skyeye-scaler
COPY --from=builder /skyeye/skyeye-scaler /opt/skyeye/bin/skyeye-scaler
ENTRYPOINT ["/opt/skyeye/bin/skyeye-scaler"]

FROM builder AS builder-vulkan
RUN apt-get update && apt-get install -y \
libvulkan-dev \
glslc \
spirv-headers \
&& rm -rf /var/lib/apt/lists/*
RUN make whisper GGML_VULKAN=1
RUN make skyeye-vulkan

FROM base AS skyeye-vulkan
# libvulkan1: Vulkan loader. mesa-vulkan-drivers: Vulkan ICDs for AMD/Intel GPUs
# passed in with --device /dev/dri. NVIDIA users don't need it: the NVIDIA
# container toolkit injects NVIDIA's own ICD. Unused ICDs are harmless.
RUN apt-get update && apt-get install -y \
libvulkan1 \
mesa-vulkan-drivers \
&& rm -rf /var/lib/apt/lists/*
COPY --from=builder-vulkan /skyeye/skyeye-vulkan /opt/skyeye/bin/skyeye
ENTRYPOINT ["/opt/skyeye/bin/skyeye"]
66 changes: 60 additions & 6 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,36 @@ EXTLDFLAGS = $(shell pkg-config $(LIBRARIES) --libs --static)
LDFLAGS += -linkmode external -extldflags "$(EXTLDFLAGS) -lgomp -static"
endif

# Experimental: Vulkan GPU acceleration for whisper.cpp (Windows and Linux).
# Build with: make skyeye-vulkan
ifeq ($(GGML_VULKAN),1)
ifeq ($(OS_DISTRIBUTION),macOS)
$(error GGML_VULKAN is not supported on macOS; the Metal backend is already used there)
endif
SKYEYE_BIN = skyeye-vulkan
ifeq ($(OS_DISTRIBUTION),Windows)
SKYEYE_BIN = skyeye-vulkan.exe
endif
# Suffix --version output to distinguish Vulkan builds
SKYEYE_VERSION := $(SKYEYE_VERSION)+vulkan
# Separate build directory so CPU-only and Vulkan whisper.cpp builds don't collide
WHISPER_CPP_BUILD_DIR = $(WHISPER_CPP_PATH)/build_go_vulkan
WHISPER_CPP_CMAKE_ARGS += -DGGML_VULKAN=ON
LIBRARY_PATHS := $(LIBRARY_PATHS):$(ABS_WHISPER_CPP_BUILD_DIR)/ggml/src/ggml-vulkan
ifeq ($(OS_DISTRIBUTION),Windows)
# Link MSYS2's Vulkan import library by full path: -static limits -l searches
# to static libraries, but explicit file arguments are always accepted. The
# path must be converted with cygpath because the linker is a native Windows
# program that doesn't understand MSYS2 paths like /ucrt64. The exe imports
# vulkan-1.dll from the GPU driver / System32 at runtime.
# Repeat -lstdc++ because the static libstdc++.a earlier in the link order is
# not re-scanned for symbols that only libggml-vulkan.a needs.
BUILD_VARS += CGO_LDFLAGS='-lggml-vulkan $(shell cygpath -m /ucrt64/lib/libvulkan-1.dll.a) -lstdc++'
else
BUILD_VARS += CGO_LDFLAGS='-lggml-vulkan -lvulkan'
endif
endif

# AMD64-specific settings (Windows and Linux)
ifeq ($(GOARCH),amd64)
# Pin CPU features explicitly instead of letting ggml auto-detect via
Expand All @@ -103,7 +133,11 @@ install-msys2-dependencies:
$(MINGW_PACKAGE_PREFIX)-toolchain \
$(MINGW_PACKAGE_PREFIX)-go \
$(MINGW_PACKAGE_PREFIX)-opus \
$(MINGW_PACKAGE_PREFIX)-libsoxr
$(MINGW_PACKAGE_PREFIX)-libsoxr \
$(MINGW_PACKAGE_PREFIX)-vulkan-headers \
$(MINGW_PACKAGE_PREFIX)-vulkan-loader \
$(MINGW_PACKAGE_PREFIX)-shaderc \
$(MINGW_PACKAGE_PREFIX)-spirv-headers

.PHONY: install-arch-linux-dependencies
install-arch-linux-dependencies:
Expand All @@ -113,7 +147,11 @@ install-arch-linux-dependencies:
cmake \
go \
opus \
libsoxr
libsoxr \
vulkan-headers \
vulkan-icd-loader \
shaderc \
spirv-headers

.PHONY: install-debian-dependencies
install-debian-dependencies:
Expand All @@ -126,7 +164,10 @@ install-debian-dependencies:
libopus-dev \
libopus0 \
libsoxr-dev \
libsoxr0
libsoxr0 \
libvulkan-dev \
glslc \
spirv-headers

.PHONY: install-fedora-dependencies
install-fedora-dependencies:
Expand All @@ -139,7 +180,11 @@ install-fedora-dependencies:
opus-devel \
opus \
soxr-devel \
sox
sox \
vulkan-headers \
vulkan-loader-devel \
glslc \
spirv-headers-devel

.PHONY: install-macos-dependencies
install-macos-dependencies:
Expand Down Expand Up @@ -179,7 +224,16 @@ generate:
$(BUILD_VARS) $(GO) generate $(BUILD_FLAGS) ./...

$(SKYEYE_BIN): generate $(SKYEYE_SOURCES) $(LIBWHISPER_PATH) $(WHISPER_H_PATH)
$(BUILD_VARS) $(GO) build $(BUILD_FLAGS) ./cmd/skyeye/
$(BUILD_VARS) $(GO) build $(BUILD_FLAGS) -o "$(SKYEYE_BIN)" ./cmd/skyeye/

# Wrapper for the experimental Vulkan build. Re-runs make with GGML_VULKAN=1,
# which renames SKYEYE_BIN to skyeye-vulkan[.exe] so the rule above builds it.
# Only defined when GGML_VULKAN is unset to avoid clashing with that rule.
ifneq ($(GGML_VULKAN),1)
.PHONY: skyeye-vulkan skyeye-vulkan.exe
skyeye-vulkan skyeye-vulkan.exe:
$(MAKE) GGML_VULKAN=1
endif

$(SKYEYE_SCALER_BIN): generate $(SKYEYE_SOURCES)
$(BUILD_VARS) $(GO) build $(BUILD_FLAGS) ./cmd/skyeye-scaler/
Expand Down Expand Up @@ -218,7 +272,7 @@ format:

.PHONY: mostlyclean
mostlyclean:
rm -f "$(SKYEYE_BIN)" "$(SKYEYE_SCALER_BIN)"
rm -f "$(SKYEYE_BIN)" "$(SKYEYE_SCALER_BIN)" skyeye-vulkan skyeye-vulkan.exe
find . -type f -name 'mock_*.go' -delete

.PHONY: clean
Expand Down
14 changes: 7 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ SkyEye is a substantial improvement over the DCS AWACS:
4. SkyEye supports a larger number of commands, including [PICTURE](docs/PLAYER.md#picture), [BOGEY DOPE](docs/PLAYER.md#bogey-dope), [DECLARE](docs/PLAYER.md#declare), [SNAPLOCK](docs/PLAYER.md#snaplock), [SPIKED](docs/PLAYER.md#spikedstrobe), [STROBE](docs/PLAYER.md#spikedstrobe), [ALPHA CHECK](docs/PLAYER.md#alpha-check) and [VECTOR](docs/PLAYER.md#vector).
5. SkyEye intelligently monitors the battlespace, providing automatic [THREAT](docs/PLAYER.md#threat), [MERGED](docs/PLAYER.md#merged) and [FADED](docs/PLAYER.md#faded) callouts to improve situational awareness.

SkyEye uses Speech-To-Text and Text-To-Speech technology which can run locally on the same computer as SkyEye. No cloud APIs are required, although cloud APIs are optionally supported. It works with any DCS mission, singleplayer or multiplayer. No special scripting or mission editor setup is required. You can run it for less than a nickel per hour on a cloud server, or run it on a computer in your home running Windows, Linux or macOS.
SkyEye uses Speech-To-Text and Text-To-Speech technology which can run locally on the same computer as SkyEye. No cloud APIs are required, although cloud APIs are optionally supported. It works with any DCS mission, singleplayer or multiplayer. No special scripting or mission editor setup is required. You can run it on a cloud server, or run it on a computer in your home running Windows, Linux or macOS.

SkyEye is production ready software. It is used by a few public servers and many private squadrons. Based on download statistics, I estimate over 100 communities are using SkyEye, such as:

Expand Down Expand Up @@ -53,7 +53,7 @@ See https://limakilo.net for server details.

On Windows and Linux, SkyEye can be downloaded from [GitHub Releases](https://github.com/dharmab/skyeye/releases).

On Linux, SkyEye is also available as a container: `ghcr.io/dharmab/skyeye:latest`. Note this container won't work on Windows or macOS.
On Linux, SkyEye is also available as a container: `ghcr.io/dharmab/skyeye:latest` (CPU version) and `ghcr.io/dharmab/skyeye:latest-vulkan` (GPU version).

On macOS, SkyEye can be installed using [Homebrew](https://brew.sh/):

Expand All @@ -67,19 +67,19 @@ See the [admin guide](docs/ADMIN.md) for detailed instructions on installing, co

### What do I need to run SkyEye?

There are a few different ways to run SkyEye. In order from best to least recommended:
There are a few different ways to run SkyEye.

1. On an Apple Sillicon Mac networked to your DCS server, using local speech recognition. This offers the fastest speech recognition and the highest quality AI voice.
2. On your DCS server, using the OpenAI API for speech recognition. This offers fast speech recognition and good quality AI voices, but requires a credit card accepted by OpenAI to purchase API credits from OpenAI. At current pricing, $1 of OpenAI credit pays to recognize more than 1000 transmissions over SRS.
3. On a separate Windows or Linux computer networked to your DCS server, using local speech recognition. This offers good-enough speech recognition performance and good quality AI voices without any credit card required. This also works with rented cloud servers, some of whom accept other payment methods compared to OpenAI.

Running SkyEye on the same computer as DCS, using local speech recognition, is not recommended and no support can be provided for that configuration. Use a separate computer or OpenAI's API instead.
2. On your Windows or Linux computer with a GPU, using local speech recognition and the experimental Vulkan build of SkyEye. This offers fast speech recognition and good quality AI voices, although the performance and quality of the speech recognition can vary based on GPU hardware and drivers.
3. On your DCS server, using the OpenAI API for speech recognition. This offers fast speech recognition and good quality AI voices, but requires a credit card accepted by OpenAI to purchase API credits from OpenAI. At current pricing, $1 of OpenAI credit pays to recognize more than 1000 transmissions over SRS.
4. On a separate Windows or Linux computer networked to your DCS server, using local speech recognition. This offers good-enough speech recognition performance and good quality AI voices without any credit card required. This also works with rented cloud servers, some of whom accept other payment methods compared to OpenAI.

### What kind of hardware does it require?

Generally, local speech recognition requires one of:

* Any Apple Silicon Mac, such as a Mac Mini or MacBook Air/Pro.
* A Windows or Linux computer with a GPU.
* A Windows or Linux computer with a fast quad-core CPU from the last 2-3 CPU generations.

Cloud speech recognition requirements are quite modest.
Expand Down
Loading
Loading