Unreal EngineにAzure Speech SDK(C++/x64)を導入する完全手順|インストーラでファイルが見つからない問題の解決策

Unreal Engine のネイティブ C++ プロジェクトに Azure Speech SDK を入れようとしても、インストーラ完了後に speechapi_cxx.h/SpeechSDK.lib/SpeechSDK.dll が見つからず先へ進めない――この“あるある”を、実運用に耐える導入手順・配置規約・ビルド設定・トラブル回避まで一気通貫で解消します。NuGet 非依存・オフライン前提の方法も網羅します。

目次

Azure Speech SDK(C++ / x64)をUnreal Engineに組み込めない問題

質問概要と現象の整理

  • Unreal Engine のネイティブ C++ プロジェクトで Azure Speech Services を使いたい。
  • Speech SDK v2.9.0 のインストーラは Setup Successful と表示されるが、以下が見つからない:
    • speechapi_cxx.h
    • SpeechSDK.lib(x64)
    • SpeechSDK.dll(x64)
  • .NET/C# や NuGet を使わず、純粋なネイティブ C++ のバイナリとヘッダを直接取得したい。

結論(要点)

  • インストーラ単体では“開発用ファイル(ヘッダ/.lib)”が見当たらないケースがある。
  • 必要ファイルは 公式サンプルのビルド または NuGet パッケージの手動展開、もしくは Windows x64 ZIP(C++ API) から取得できる。
  • Unreal への組み込みは ThirdParty 配置 + Build.cs + DLL のステージング までがワンセット。遅延ロード設定やランタイム整合も忘れずに。

アーキテクチャと配布仕様の前提知識

  • Speech SDK の C++ は インポートライブラリ(.lib)+ DLL の動的リンクが前提。静的リンク(.lib 単体)では完結しない設計です。
  • DLL は x64 のみ。Unreal のターゲットも Win64 固定にします(Win32/ARM64 非対応前提で設計)。
  • 配布形態はバージョンにより MSI(インストーラ)/ZIP/NuGet のいずれか(または併存)。欲しいのは ヘッダ・.lib・.dll の 3 点セットです。

解決策:3つの確実な入手ルート

1) 公式 C++ サンプルをビルドして展開させる(推奨)

Microsoft 公式の C++ サンプル(例:samples/cpp/windows/console)をビルドすると、必要な include/lib/dll がローカルに自動展開されます。インストーラは“実行時コンポーネント主体”で、開発用ファイルはサンプルのビルド時に解凍・配置される構成になっていることがあります。

  1. サンプルを取得し、Visual Studio で開く(または同梱のソリューションを起動)。
  2. x64 / Release でビルド。
  3. 出力ディレクトリ(例:./x64/Release/)や packages 相当のワークフォルダに、SpeechSDK.dll/SpeechSDK.lib/include 一式が展開されていることを確認。

この方法の利点は、公式が想定する導入経路であるため依存関係が自動的に揃う点です。

2) NuGet パッケージ(.nupkg)を ZIP として手動展開する(オフラインでも再現性◎)

NuGet を Unreal で使いたくない/使えない場合でも、Microsoft.CognitiveServices.Speech の .nupkg は ZIP 互換です。以下で必要ファイルを取り出せます。

rem 1) nupkg を取得(NuGet クライアントがある前提)
nuget.exe install Microsoft.CognitiveServices.Speech -Version 2.9.0 -OutputDirectory .

rem 2) 生成された *.nupkg を *.zip にリネームして展開
ren Microsoft.CognitiveServices.Speech.2.9.0.nupkg Microsoft.CognitiveServices.Speech.2.9.0.zip
tar -xf Microsoft.CognitiveServices.Speech.2.9.0.zip

rem 3) 中身の確認(バージョンで若干異名あり)
build/native/include/              => ヘッダ一式(speechapi_cxx.h など)
runtimes/win-x64/native/           => SpeechSDK.dll
build/native/x64/   または lib/win-x64/ => SpeechSDK.lib 

取り出した 3 点セットを、Unreal プロジェクトの Plugins/YourPlugin/Source/ThirdParty/AzureSpeechSDK/ 配下に配置します(後述)。

3) Windows x64 ZIP(C++ API)を選ぶ

バージョンによっては公式のダウンロードページに Windows x64 ZIP(C++ API) が用意されています。MSI ではなく ZIP を選ぶと、展開だけで include / lib / dll の全てが揃うので最短です。該当 ZIP が見つからない場合は、以前のバージョンやリリースアーカイブを確認してください。

各方法の比較

項目メリットデメリット
サンプルビルド最小手間/依存が自動で揃う/公式想定経路サンプルをビルドできる環境が必要
NuGet 手動展開完全オフライン対応/バージョン固定が容易/CI に向くCLI 操作・手作業が必要/構成の読み解きが必要
ZIP 版クリック展開だけで揃う/手早い全バージョンで提供されるとは限らない

Unreal Engine への安全な組み込みテンプレート

フォルダ設計(ThirdParty 方式)

Plugins/
└─ YourPlugin/
   ├─ YourPlugin.uplugin
   └─ Source/
      ├─ YourPlugin/
      │  ├─ YourPlugin.Build.cs
      │  ├─ Public/(必要なら)
      │  └─ Private/(必要なら)
      └─ ThirdParty/
         └─ AzureSpeechSDK/
            ├─ include/          (speechapi_cxx.h など)
            ├─ lib/
            │  └─ SpeechSDK.lib
            └─ bin/
               └─ SpeechSDK.dll

Build.cs(単一モジュールに直書きする簡易版)

DLL を遅延ロードし、パッケージ時に自動コピー(ステージング)されるようにします。例は UE5 系想定です。

using UnrealBuildTool;
using System.IO;

public class YourPlugin : ModuleRules
{
public YourPlugin(ReadOnlyTargetRules Target) : base(Target)
{
PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;
    // 例: 例外を使う場合。Speech SDK を UE の例外禁止ポリシーから分離
    bEnableExceptions = true;

    // ThirdParty/AzureSpeechSDK を指す
    string SdkRoot = Path.Combine(ModuleDirectory, "..", "ThirdParty", "AzureSpeechSDK");
    string SdkInclude = Path.Combine(SdkRoot, "include");
    string SdkLib     = Path.Combine(SdkRoot, "lib");
    string SdkBin     = Path.Combine(SdkRoot, "bin");

    PublicIncludePaths.Add(SdkInclude);

    if (Target.Platform == UnrealTargetPlatform.Win64)
    {
        PublicAdditionalLibraries.Add(Path.Combine(SdkLib, "SpeechSDK.lib"));

        // 起動直後のロード失敗を避けるため遅延ロード
        PublicDelayLoadDLLs.Add("SpeechSDK.dll");

        // パッケージング & 実行に必要な DLL をステージング
        RuntimeDependencies.Add(Path.Combine(SdkBin, "SpeechSDK.dll"));
    }

    PublicDefinitions.Add("NOMINMAX=1");             // Windows ヘッダの副作用抑制
    PublicDefinitions.Add("_CRT_SECURE_NO_WARNINGS"); // MSVC の警告を抑制(任意)
}

} 

uplugin(Win64 固定・ランタイムモジュール)

{
  "FileVersion": 3,
  "VersionName": "1.0.0",
  "FriendlyName": "Azure Speech SDK Bridge",
  "Description": "Azure Speech SDK (C++/x64) integration for Unreal Engine.",
  "Category": "Runtime",
  "CanContainContent": false,
  "IsBetaVersion": false,
  "Modules": [
    {
      "Name": "YourPlugin",
      "Type": "Runtime",
      "LoadingPhase": "Default",
      "SupportedTargetPlatforms": [ "Win64" ]
    }
  ]
}

推奨ビルド設定

項目推奨設定理由
ランタイムライブラリ/MD または /MT(DLL と一致)ランタイム不一致によるクラッシュを防ぐ
Windows SDK10.0.18362 以降SpeechSDK.dll の依存関係を満たす
プラットフォームx64 固定公式 DLL が Win64 のみ
例外bEnableExceptions = true(モジュール単位)Speech SDK の C++ ラッパ例外に備える
C++ 標準C++17 以上将来のサンプルやユーティリティに備える

最小コード:Unreal から C++ API を叩く

環境変数でキーとリージョンを与える

ハードコーディングは避け、OS 環境変数(例:AZURE_SPEECH_KEY、AZURE_SPEECH_REGION)から取得します。

サンプル:ワンショット音声認識

// YourPluginPrivate.h 等で
#include "CoreMinimal.h"

// Speech SDK
#include 

using namespace Microsoft::CognitiveServices::Speech;
using namespace Microsoft::CognitiveServices::Speech::Audio;

// UE 側のユーティリティ関数例
static FString GetEnvUTF8(const TCHAR* Name)
{
TCHAR Buffer[512];
FPlatformMisc::GetEnvironmentVariable(Name, Buffer, UE_ARRAY_COUNT(Buffer));
return FString(Buffer);
}

void FYourPlugin::RecognizeOnce()
{
const FString Key    = GetEnvUTF8(TEXT("AZURE_SPEECH_KEY"));
const FString Region = GetEnvUTF8(TEXT("AZURE_SPEECH_REGION"));
if (Key.IsEmpty() || Region.IsEmpty())
{
    UE_LOG(LogTemp, Error, TEXT("Speech key/region is not set in environment variables."));
    return;
}

auto Config      = SpeechConfig::FromSubscription(TCHAR_TO_UTF8(*Key), TCHAR_TO_UTF8(*Region));
auto AudioConfig = AudioConfig::FromDefaultMicrophoneInput();
auto Recognizer  = SpeechRecognizer::FromConfig(Config, AudioConfig);

auto Result = Recognizer->RecognizeOnceAsync().get();
if (Result->Reason == ResultReason::RecognizedSpeech)
{
    UE_LOG(LogTemp, Log, TEXT("Recognized: %s"), UTF8_TO_TCHAR(Result->Text.c_str()));
}
else
{
    UE_LOG(LogTemp, Warning, TEXT("No speech recognized. Reason=%d"), (int)Result->Reason);
}

} 

ポイント:

  • UTF8_TO_TCHAR/TCHAR_TO_UTF8 で UE の文字列と SDK の UTF-8 を相互変換。
  • モジュール内のみ bEnableExceptions = true とし、エンジン全体の方針に影響を与えない。
  • エディタ実行でもマイクにアクセスできるよう Windows のプライバシー設定を確認。

DLL 配置とステージングの実務

  • エディタ実行: SpeechSDK.dll は Plugins/YourPlugin/Source/ThirdParty/AzureSpeechSDK/bin/ に置き、RuntimeDependencies で 自動ステージング。コピー先はビルド成果物の Binaries/Win64 相当です。
  • パッケージ: Packaging 設定に依存せずコピーされるよう、RuntimeDependencies.Add(...) を必ず設定。追加の依存 DLL がある場合は同様に登録します。
  • 遅延ロード: PublicDelayLoadDLLs.Add("SpeechSDK.dll"); により、起動時の即時ロードを回避。初回利用タイミングでロードされるため、足りない DLL がどこかで補完される猶予が生まれます。

よくある配置ミス

  • DLL を Content/ 以下に置いてもロード対象にならない。
  • YourPlugin/Binaries/Win64 へ手動コピーし忘れ(エディタ実行でロード失敗)。
  • CI/パッケージ時に 相対パス解決が壊れる。ModuleDirectory からの Path.Combine を徹底。

トラブルシューティング集(症状別)

1) Editor 起動時に「指定されたモジュールが見つかりません」

原因: SpeechSDK.dll が解決できていない/依存 DLL(同梱の core など)が不足。
対処: RuntimeDependencies で DLL をステージング。Binaries/Win64 に期待通りコピーされたか確認。dumpbin /DEPENDENTS SpeechSDK.dll で依存 DLL を特定し、同梱が必要なら同階層に置く。

2) LNK2019/LNK2001(未解決の外部シンボル)

原因: SpeechSDK.lib のリンク漏れ、または lib ディレクトリの追加忘れ。
対処: PublicAdditionalLibraries.Add(Path.Combine(SdkLib, "SpeechSDK.lib")) と、PublicIncludePaths.Add(SdkInclude) の両方を見直す。

3) 例外設定が原因のハング/クラッシュ

原因: モジュールが例外を投げるが、UE のコンパイル設定で例外が無効。
対処: 当該モジュールでのみ bEnableExceptions = true。プロジェクト全体を有効化しない。

4) ランタイム不一致(/MD と /MT の取り違え)

症状: 予期しないクラッシュやランタイム再配布パッケージ不足。
対処: SDK のビルド設定に合わせ、プロジェクトも /MD 系に統一(または /MT に統一)。混在させない。

5) エンコード不一致で文字化け

原因: UE の FString と SDK の UTF-8(std::string)の相互変換漏れ。
対処: TCHAR_TO_UTF8/UTF8_TO_TCHAR マクロで必ず変換してログや UI へ渡す。

6) パッケージ後のみ失敗する

原因: 編集時は「運よく見つかる」DLL がパッケージではステージされていない。
対処: RuntimeDependencies に 明示 で DLL を登録。パッケージ成果物の Windows/<GameName>/Binaries/Win64 に DLL が存在することを確認。

ビルド・運用チェックリスト

  • x64 固定: ターゲットを Win64 のみに限定(uplugin の SupportedTargetPlatforms)。
  • Windows SDK 10.0.18362 以降: プロジェクトの Windows Platform SDK を確認。
  • 依存 DLL の棚卸: dumpbin /DEPENDENTS または類似ツールで SpeechSDK.dll の依存を把握。
  • CI/CD での再現性: NuGet 手動展開または ZIP 展開をスクリプト化し、完全にソース管理(Artifacts)へ。
  • 鍵とリージョン: 環境変数/CI シークレットから注入。バイナリやリポジトリにシークレットを入れない。

オフライン・エアギャップ環境の運用ノウハウ

  1. 社内端末で .nupkg または ZIP を取得。
  2. 検証端末でウイルススキャン後、ThirdParty/AzureSpeechSDK へ展開。
  3. ハッシュ(SHA-256 など)を ThirdParty/README.md に記録して改ざん検出を担保。
  4. CI の キャッシュ/アーティファクト に登録し、毎ビルドのダウンロードを廃止。

この流れにしておくと、監査対応やバージョン追跡が劇的に楽になります。

Unreal らしい落とし穴と回避策

  • ホットリロード絡み: DLL のロックで置換できないときは UE を再起動。ステージング DLL は 常に上書き できるようにパスを一本化。
  • Editor と Game の DLL 探索差: Editor 実行は開発環境の PATH に救われがち。パッケージ時に壊れる構成は NG。あくまでステージングで完結させる。
  • UAT(Unreal Automation Tool)との相性: ビルドログに RuntimeDependencies のコピー結果が出る。ここで DLL 名のスペルや大文字小文字を確認。

ビルド設定の詳細(深掘り)

設定項目推奨値補足
OptimizationRelease / ShippingSpeech SDK の非同期 I/O で GC/スレッドのオーバーヘッドを抑制
RTTI既定(不要)Speech SDK 側で RTTI 前提の実装は通常なし。 UE 側の方針に合わせる
マルチスレッドデフォルトSDK は内部でスレッド使用。UE のタスクグラフと併用に注意
文字コードUTF-8 互換SDK は UTF-8 前提。TCHAR 変換マクロを徹底

チェック用クイック手順(コピペ可)

  1. 入手:サンプルビルド or NuGet 手動展開 or ZIP 展開で include/lib/dll を用意。
  2. 配置:Plugins/YourPlugin/Source/ThirdParty/AzureSpeechSDK/
    • include/ にヘッダ
    • lib/ に SpeechSDK.lib
    • bin/ に SpeechSDK.dll
  3. YourPlugin.Build.cs に PublicIncludePaths/PublicAdditionalLibraries/PublicDelayLoadDLLs/RuntimeDependencies を追加。
  4. uplugin に "SupportedTargetPlatforms": ["Win64"] を追加。
  5. 最小コードで RecognizeOnce を動かしてログに結果を出力。
  6. パッケージし、Binaries/Win64 に SpeechSDK.dll が入っているかを確認。

FAQ

MSI を入れ直しても見つからないのはなぜ?

配布仕様上、MSI は主としてランタイムやサンプルの取得に留まり、開発用のヘッダ/.lib はサンプルビルド時に展開される場合があります。NuGet の手動展開または ZIP 版を利用すると手早く揃います。

依存 DLL 名は増減する?

バージョンにより構成が変わることがあります。dumpbin /DEPENDENTS SpeechSDK.dll で実際に確認し、必要な DLL を同階層に配置してください。

エディタから C# を使わないのに大丈夫?

はい。C++ API のみで完結します(.NET ランタイムは不要)。Unreal の C++ モジュールから直接ヘッダ/.lib/.dll を参照してください。

ライセンスや配布上の注意は?

配布規約やエンドユーザーへの DLL 同梱可否は製品規定に従います。企業利用では社内ポリシーに沿ってバージョン固定・ハッシュ記録・配布手順を整備してください。

まとめ:つまずきやすい“最後の 1 マイル”を確実に越える

  • インストーラだけでは開発ファイルが見つからないことがある――これは想定内の挙動。
  • サンプルビルドかNuGet 手動展開、またはZIP 版で include/lib/dll を揃える。
  • Unreal への統合は ThirdParty 配置+Build.cs+DLL ステージング+遅延ロード の 4 点で安定化。
  • 文字コード・例外・ランタイム整合をチェックし、Editor と Package の双方で検証する。

以上の手順をテンプレート化しておけば、プロジェクトごとに迷うことなく、Azure Speech Services を Unreal の C++ ランタイムにスムーズに組み込めます。

付録:チェック表(印刷・レビュー向け)

チェック項目状態備考
Speech SDK のヘッダ/.lib/.dll が ThirdParty に配置済み□include / lib / bin の 3 フォルダ
Build.cs に Include/Lib/DelayLoad/RuntimeDependencies□ステージングが入っているか
uplugin が Win64 固定□SupportedTargetPlatforms
例外・ランタイム・Windows SDK の整合□表に従って設定
RecognizeOnce の最小テストが成功□ログで確認
パッケージ後の Binaries/Win64 に DLL が存在□実行端末で起動確認
依存 DLL の棚卸と記録(必要時)□dumpbin /DEPENDENTS

参考:Build.cs を外部モジュールに分離する版(応用)

運用規模が大きい場合、Speech SDK を External Module として分離しておくと再利用しやすくなります。

// Source/AzureSpeechSDK/AzureSpeechSDK.Build.cs
using UnrealBuildTool;
using System.IO;

public class AzureSpeechSDK : ModuleRules
{
public AzureSpeechSDK(ReadOnlyTargetRules Target) : base(Target)
{
Type = ModuleType.External;
    string Root = Path.Combine(ModuleDirectory, "..", "ThirdParty", "AzureSpeechSDK");
    string Inc  = Path.Combine(Root, "include");
    string Lib  = Path.Combine(Root, "lib");
    string Bin  = Path.Combine(Root, "bin");

    PublicIncludePaths.Add(Inc);

    if (Target.Platform == UnrealTargetPlatform.Win64)
    {
        PublicAdditionalLibraries.Add(Path.Combine(Lib, "SpeechSDK.lib"));
        PublicDelayLoadDLLs.Add("SpeechSDK.dll");
        RuntimeDependencies.Add(Path.Combine(Bin, "SpeechSDK.dll"));
    }

    bEnableExceptions = true;
}

}
// 使う側(YourPlugin.Build.cs)では
// PrivateDependencyModuleNames.AddRange(new[] { "AzureSpeechSDK" }); 

運用の“クセ”も含めたメリット・デメリット(再掲)

方式メリットデメリット
サンプルビルド最小限の手間。公式が想定する導入で依存が揃うビルド環境の整備が前提
NuGet 手動抽出完全オフライン対応/バージョン固定・再現性に強いCLI 操作や手動展開の手間
公式 ZIP 版展開だけで完了。導入スピード最優先欲しいバージョンが提供されないことがある

最終ポイントまとめ

  • インストーラ単体では“開発用ファイル”が無いことがあるのは仕様。
  • 必要ファイルは「サンプルビルド」か「NuGet 手動抽出」または「ZIP 版」で確実に取得。
  • Unreal 統合は ThirdParty 配置・Build.cs 設定・DLL ステージング・遅延ロードの 4 点セット。
  • ランタイム整合(/MD vs /MT)、Windows SDK、文字コード、例外設定を必ず確認。

この記事を書いた人

実務の現場で詰まりがちなポイントを地図にするITブログ「IT trip」を運営。Windows/Office(Teams・Excel)からSQL、サーバ運用、ガジェットまで、再現性のある手順と“なぜそうなるか”を丁寧に解説します。読んだらすぐ試せること、そして迷った人の次の一歩が見えることを大切にしています。

コメント

コメントする

目次