Skip to content

Air Light VR

Stream VR games from your PC to your headset via Wi-Fi.

About

ALVR은 "Air Light VR"의 줄임말로, PC VR 게임을 무선으로 스탠드얼론 VR 헤드셋(주로 Meta Quest 시리즈)에서 플레이할 수 있게 해주는 오픈소스 스트리밍 소프트웨어입니다.

주요 기능은 다음과 같습니다:

  • 무선 PC VR 스트리밍: PC에서 실행되는 SteamVR 게임들을 Wi-Fi를 통해 Quest 헤드셋으로 전송하여 케이블 없이 플레이할 수 있게 합니다.
  • 저지연 전송: 게임 플레이에 지장이 없도록 낮은 지연시간으로 비디오와 오디오를 실시간 스트리밍합니다.
  • 무료 오픈소스: 상용 솔루션인 Virtual Desktop이나 Meta의 Air Link와 달리 완전히 무료로 사용할 수 있습니다.
  • 커스터마이징 가능: 인코딩 설정, 해상도, 비트레이트 등을 세밀하게 조정할 수 있어 사용자의 네트워크 환경에 맞게 최적화할 수 있습니다.

PC에 ALVR 서버를 설치하고 Quest 헤드셋에 ALVR 클라이언트를 설치한 후 연결하면, Half-Life: Alyx, Beat Saber 같은 PC VR 게임들을 무선으로 즐길 수 있습니다. 안정적인 5GHz Wi-Fi 환경에서 최적의 성능을 발휘합니다.

alvr_fw_config.sh

설치하다보면 방화벽 개방해야 한다해서 관리자 권한 요구함. 해당 스크립트는 다음과 같다:

#!/usr/bin/env bash
# Basic script to add / remove firewall configuration for ALVR
# Usage: ./alvr_fw_config.sh add|remove
# Exit codes:
# 1 - Invalid command
# 2 - Invalid action
# 3 - Failed to copy UFW configuration
# 99 - Firewall not found
# 126 - pkexec failed - Request dismissed

firewalld_cfg() {
    # Iterate around each active zone
    for zone in $(firewall-cmd --get-active-zones | grep -P '^\w+'); do
        if [ "${1}" == 'add' ]; then
            # If running or permanent alvr service is missing, add it
            if ! firewall-cmd --zone="${zone}" --list-services | grep 'alvr' >/dev/null 2>&1; then
                firewall-cmd --zone="${zone}" --add-service='alvr'
            fi
            if ! firewall-cmd --zone="${zone}" --list-services --permanent | grep 'alvr' >/dev/null 2>&1; then
                firewall-cmd --zone="${zone}" --add-service='alvr' --permanent
            fi
        elif [ "${1}" == 'remove' ]; then
            # If running or persistent alvr service exists, remove it
            if firewall-cmd --zone="${zone}" --list-services | grep 'alvr' >/dev/null 2>&1; then
                firewall-cmd --zone="${zone}" --remove-service='alvr'
            fi
            if firewall-cmd --zone="${zone}" --list-services --permanent | grep 'alvr' >/dev/null 2>&1; then
                firewall-cmd --zone="${zone}" --remove-service='alvr' --permanent
            fi
        else
            exit 2
        fi
    done
}

ufw_cfg() {
    # Try and install the application file
    if ! ufw app info 'alvr'; then
        # Pull application file from local build first if the script lives inside it
        if [ -f "$(dirname "$(realpath "${0}")")/ufw-alvr" ]; then
            cp "$(dirname "$(realpath "${0}")")/ufw-alvr" '/etc/ufw/applications.d/'
        elif [ -f '/usr/share/alvr/ufw-alvr' ]; then
            cp '/usr/share/alvr/ufw-alvr' '/etc/ufw/applications.d/'
        else
            exit 3
        fi
    fi

    if [ "${1}" == 'add' ] && ! ufw status | grep 'alvr' >/dev/null 2>&1; then
        ufw allow 'alvr'
    elif [ "${1}" == 'remove' ] && ufw status | grep 'alvr' >/dev/null 2>&1; then
        ufw delete allow 'alvr'
    else
        exit 2
    fi
}

iptables_cfg() {
    first_port_match_count=$(iptables -S | grep -c '9943')
    second_port_match_count=$(iptables -S | grep -c '9944')
    if [ "${1}" == 'add' ]; then
        if [ "$first_port_match_count" == "0" ] || [ "$second_port_match_count" == "0" ]; then
            if [ ! -d '/etc/iptables' ]; then
                mkdir '/etc/iptables'
            fi

            iptables -I OUTPUT -p tcp --sport 9943 -j ACCEPT
            iptables -I INPUT -p tcp --dport 9943 -j ACCEPT
            iptables -I OUTPUT -p udp --sport 9943 -j ACCEPT
            iptables -I INPUT -p udp --dport 9943 -j ACCEPT
            iptables -I OUTPUT -p tcp --sport 9944 -j ACCEPT
            iptables -I INPUT -p tcp --dport 9944 -j ACCEPT
            iptables -I OUTPUT -p udp --sport 9944 -j ACCEPT
            iptables -I INPUT -p udp --dport 9944 -j ACCEPT
            iptables-save >/etc/iptables/rules.v4
        fi
    elif [ "${1}" == 'remove' ]; then
        if [ "$first_port_match_count" == "4" ] || [ "$second_port_match_count" == "4" ]; then
            iptables -D OUTPUT -p tcp --sport 9943 -j ACCEPT
            iptables -D INPUT -p tcp --dport 9943 -j ACCEPT
            iptables -D OUTPUT -p udp --sport 9943 -j ACCEPT
            iptables -D INPUT -p udp --dport 9943 -j ACCEPT
            iptables -D OUTPUT -p tcp --sport 9944 -j ACCEPT
            iptables -D INPUT -p tcp --dport 9944 -j ACCEPT
            iptables -D OUTPUT -p udp --sport 9944 -j ACCEPT
            iptables -D INPUT -p udp --dport 9944 -j ACCEPT
            iptables-save >/etc/iptables/rules.v4
        fi
    else
        exit 2
    fi
}

main() {
    # If we're not root use pkexec for GUI prompt
    if [ "${USER}" == 'root' ]; then
        # Check if firewall-cmd exists and firewalld is running
        if which firewall-cmd >/dev/null 2>&1 && firewall-cmd --state >/dev/null 2>&1; then
            firewalld_cfg "${1,,}"
        # Check if ufw exists and is running
        elif which ufw >/dev/null 2>&1 && ! ufw status | grep 'Status: inactive' >/dev/null 2>&1; then
            ufw_cfg "${1,,}"
        elif which iptables >/dev/null 2>&1; then
            iptables_cfg "${1,,}"
        else
            exit 99
        fi
    else
        pkexec "$(realpath "${0}")" "${@}"
    fi
}

main "${@}"

See also

Favorite site