言語
Video Super Resolution (VSR) は AI ベースのビデオ アップ サンプリング テクノロジであり、人々の低解像度のビデオ ストリームをインテリジェントにスケールアップし、帯域幅の制限、ネットワーク条件の低下、圧縮、または低品質のソース コンテンツによって失われる可能性のある鮮明さと詳細を復元します。
アプリに VSR 機能を追加すると、次のようなシナリオが可能になります。
- ネットワーク接続が不十分な場合のビデオ品質の向上
- CDN コストを削減するための帯域幅の最適化
- 複数の参加者によるグループ ビデオ通話などの高帯域幅シナリオ
- 編集、アップロード、または表示におけるソーシャル メディア ビデオの品質の向上
VSR 機能は、Copilot+ PCs と NPU、および で推奨される CPU 仕様を満たすデバイスで使用できます。 詳細については、Copilot+ PCs 用の
サポートされているハードウェア
| Hardware | 地位 | 詳細情報 |
|---|---|---|
| NPU (Copilot+ PC) | ✅ 使用可能 | 最高のパフォーマンスを発揮します。 Copilot+ PCs開発者ガイドを参照してください。 |
| CPU | ✅ 使用可能 | 推奨される CPU 仕様を満たすデバイスに最適です。 VSR は下位仕様のデバイスで引き続き実行を試みますが、リアルタイムの品質とフレーム レートが低下する可能性があります。 |
| GPU | ❌ サポートされていません | VSR は GPU では使用できません。 |
Note
ハードウェアの選択は自動的に行われます。 NPU を使用するCopilot+ PCでは、VSR は常に NPU で実行されます。 Copilot+ ではないデバイスでは、VSR は CPU で自動的に実行されます。Copilot+ デバイスで CPU を選択するための、開発者またはエンド ユーザーによるオプトインはありません。 これは、他のWindows AI API で使用されるパターンと一致します。クロス API ビューについては、サポートされているハードウェアを参照してください。
これらの VSR API は Machine Learning (ML) モデルを使用します。ビデオ通話や会議アプリ、人の顔を話すソーシャルビデオや短い形式のビデオなどのシナリオ専用に設計されています
VSR では現在、次の解像度、形式、FPS 範囲がサポートされています。
| 特性 | サポートされているコンテンツ |
|---|---|
| 入力解像度 | 240p – 1440p |
| 出力解像度 | 480p ~ 1440p (オフライン ビデオ処理用 4K) |
| 1 秒あたりのフレーム数 (FPS) 範囲 | 15 fps – 60 fps |
| 入力ピクセル形式 | BGR (ImageBuffer API)、NV12 (Direct3D API) |
| 出力ピクセル形式 | BGR (ImageBuffer API)、BGRA、NV12 (Direct3D API) |
推奨される CPU 仕様
VSR モデルはWindows アプリ SDKの一部として提供されるため、CPU デバイスに個別のダウンロードまたは初回実行の同意手順はありません。 VSR は、他の Windows AI API が動作する任意の CPU 上で動作しますが、リアルタイム スケーリングの品質とフレーム レートはホスト CPU の性能に応じて変化します。
優れた CPU エクスペリエンスを実現するために、次の推奨仕様 をすべて 満たすデバイスをターゲットにしてください。
- 4 つ以上の物理コア
- 3 GHz 以上のベース クロック
- 32 MB 以上の L3 キャッシュ
これらは推奨事項であり、ハードな最小値ではありません。API は引き続き、より低い仕様のデバイスでのスケーリングを試みます。 広範な CPU 範囲を対象とするアプリは、実行時に CPU に対してクエリを実行し、デバイスが推奨されるバーを下回った場合は、VSR 以外のパイプラインにフォールバックするか、品質トレードオフのヒントをユーザーに表示する必要があります。
Note
GetReadyState と CPU スペック チェックは さまざまな 質問に回答し、一緒に使用する必要があります。
GetReadyState は、VSR がデバイスでまったくサポートされているかどうかを示します (モデルが読み込まれ、ドライバーが存在し、ハードウェア ポリシーで許可されます)。 CPUスペックチェックでは、VSR がその UX で 十分に 動作するかどうかを確認できます。
GetReadyStateを使用して VSR を呼び出すかどうかを決定します。CPU チェックを使用して、境界ハードウェア上の VSR と軽量フォールバック (バイリニア アップスケールなど) を決定します。
CPU サポート レベルを確認する
次の C# サンプルでは、Windows 管理インストルメンテーション (WMI) を使用して Win32_Processor クラスに対してクエリを実行し、デバイスが推奨仕様を満たしている場合は true を返します。 このサンプルでは、Microsoft発行された System.Management NuGet パッケージ (WMI の標準.NET ラッパー) を使用して、C# から WMI を呼び出します。
using System;
using System.Management;
private static bool MeetsRecommendedCpuSpecs()
{
const int RecommendedCores = 4;
const int RecommendedClockMhz = 3000;
const int RecommendedL3CacheKb = 32 * 1024; // 32 MB
int totalCores = 0;
int maxClockMhz = 0;
int maxL3CacheKb = 0;
using var searcher = new ManagementObjectSearcher(
"SELECT NumberOfCores, MaxClockSpeed, L3CacheSize FROM Win32_Processor");
foreach (ManagementObject processor in searcher.Get())
{
totalCores += Convert.ToInt32(processor["NumberOfCores"]);
maxClockMhz = Math.Max(maxClockMhz, Convert.ToInt32(processor["MaxClockSpeed"]));
maxL3CacheKb = Math.Max(maxL3CacheKb, Convert.ToInt32(processor["L3CacheSize"]));
}
return totalCores >= RecommendedCores
&& maxClockMhz >= RecommendedClockMhz
&& maxL3CacheKb >= RecommendedL3CacheKb;
}
結果を使用して UX の選択肢をゲートします。たとえば、品質トレードオフのヒントを表示したり、既定で出力解像度を低くしたり、推奨事項を下回るデバイスで VSR を完全にスキップしたりできます。
WMI チェックに関する注意事項
- 結果をキャッシュします。 最初の WMI クエリは、COM の初期化のために約 50 ~ 200 ミリ秒かかります。 後続のクエリは高速ですが、最もクリーンなパターンは、起動時に
MeetsRecommendedCpuSpecs1 回実行し、プロセスの有効期間中にブール値をキャッシュすることです。 CPU ハードウェアは実行時に変更されません。 -
MaxClockSpeedは、ブースト クロックではなく、定格ベース クロックです。 4.5 GHz にターボする 2.5 GHz CPU は、2500を報告し、3 GHz チェックに失敗します。 これは意図的なものであり、継続的なスループットは VSR などの AI ワークロードのストリーミングのピーク ブーストよりも重要であるため、ベース クロックが適切なシグナルです。 - ミリ秒未満のチェックの代替。
System.Managementの依存関係を回避する必要がある場合、または WMI コストが許容できない場合 (ホット スタートアップ パスなど)、ネイティブ Windows API を通じて同じデータを使用できます。GetLogicalProcessorInformationExはコア数とキャッシュ サイズを返し、定格クロック速度はHKLM\HARDWARE\DESCRIPTION\System\CentralProcessor\0(~MHz値) で公開されます。 これらはミリ秒未満の時間で返されますが、より多くのコードが必要です。
VideoScaler セッションを作成する
次の例は、VSR セッションを作成する方法を示しています。 まず、 ExecutionProviderCatalog のインスタンスを取得し、 EnsureAndRegisterCertifiedAsync を呼び出して使用可能なモデルを読み込みます。 VideoScaler クラスで GetReadyState を呼び出して、ビデオ スケーラーがフレームを処理する準備ができているかどうかを判断します。 そうでない場合は、 EnsureReadyAsync を呼び出してビデオ スケーラーを初期化します。
using Microsoft.Windows.AI;
using Microsoft.Windows.AI.MachineLearning;
using Microsoft.Windows.AI.Video;
private VideoScaler? _videoScaler;
protected override async Task LoadModelAsync(SampleNavigationParameters sampleParams)
{
try
{
var catalog = ExecutionProviderCatalog.GetDefault();
await catalog.EnsureAndRegisterCertifiedAsync();
var readyState = VideoScaler.GetReadyState();
if (readyState == AIFeatureReadyState.NotSupportedOnCurrentSystem)
{
// VSR cannot run on this device. Fall back to a non-VSR pipeline
// (for example, a bilinear or bicubic upscaler) or hide the feature.
ShowException(null, "Video Super Resolution is not supported on this device.");
return;
}
if (readyState == AIFeatureReadyState.NotReady)
{
var operation = await VideoScaler.EnsureReadyAsync();
if (operation.Status != AIFeatureReadyResultState.Success)
{
ShowException(null, "Video Scaler is not available.");
return;
}
}
_videoScaler = await VideoScaler.CreateAsync();
}
catch (Exception ex)
{
ShowException(ex, "Failed to load model.");
}
sampleParams.NotifyCompletion();
}
VideoFrame のスケーリング
次のコード例では、 VideoScaler.Scale メソッドを使用して 、VideoFrame オブジェクトに含まれるイメージ データをアップスケールします。 MediaFrameReader クラスを使用して、カメラから VideoFrame を取得できます。 詳細については、「 MediaFrameReader を使用したメディア フレームの処理」を参照してください。 WinUI Community Toolkit CameraPreview コントロールを使用して、カメラから VideoFrame オブジェクトを取得することもできます。
次に、入力ビデオ フレームから Direct3DSurface を取得し、アップスケーリングの出力用に別の Direct3DSurface を作成します。 VideoScaler.Scale は、フレームをアップスケールするために呼び出されます。 この例では、アプリの UI の Image コントロールがアップスケール されたフレームで更新されます。
private async Task ProcessFrame(VideoFrame videoFrame)
{
// Process the frame with super resolution model
var processedBitmap = await Task.Run(async () =>
{
int width = 0;
int height = 0;
var inputD3dSurface = videoFrame.Direct3DSurface;
if (inputD3dSurface != null)
{
Debug.Assert(inputD3dSurface.Description.Format == Windows.Graphics.DirectX.DirectXPixelFormat.NV12, "input in NV12 format");
width = inputD3dSurface.Description.Width;
height = inputD3dSurface.Description.Height;
}
else
{
var softwareBitmap = videoFrame.SoftwareBitmap;
if (softwareBitmap == null)
{
return null;
}
Debug.Assert(softwareBitmap.BitmapPixelFormat == BitmapPixelFormat.Nv12, "input in NV12 format");
width = softwareBitmap.PixelWidth;
height = softwareBitmap.PixelHeight;
}
try
{
if (inputD3dSurface == null)
{
// Create Direct3D11-backed VideoFrame for input
using var inputVideoFrame = VideoFrame.CreateAsDirect3D11SurfaceBacked(
Windows.Graphics.DirectX.DirectXPixelFormat.NV12,
width,
height);
if (inputVideoFrame.Direct3DSurface == null)
{
return null;
}
// Copy the software bitmap to the Direct3D-backed frame
await videoFrame.CopyToAsync(inputVideoFrame);
inputD3dSurface = inputVideoFrame.Direct3DSurface;
}
// Create or resize output surface (BGRA8 format for display)
if (_outputD3dSurface == null || _outputWidth != width || _outputHeight != height)
{
_outputD3dSurface?.Dispose();
// DXGI_FORMAT_B8G8R8A8_UNORM = 87
_outputD3dSurface = Direct3DExtensions.CreateDirect3DSurface(87, width, height);
_outputWidth = width;
_outputHeight = height;
}
// Scale the frame using VideoScaler
var result = _videoScaler!.Scale(inputD3dSurface, _outputD3dSurface, new VideoScalerOptions());
if (result.Status == VideoScalerStatus.Success)
{
var outputBitmap = await SoftwareBitmap.CreateCopyFromSurfaceAsync(
_outputD3dSurface,
BitmapAlphaMode.Premultiplied);
return outputBitmap;
}
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine($"ProcessFrame error: {ex.Message}");
}
return null;
});
if (processedBitmap == null)
{
return;
}
DispatcherQueue.TryEnqueue(async () =>
{
using (processedBitmap)
{
var source = new SoftwareBitmapSource();
await source.SetBitmapAsync(processedBitmap);
ProcessedVideoImage.Source = source;
}
});
}
ImageBuffer を使用して SoftwareBitmap をスケーリングする
次のコード例は、 VideoScaler クラスを使用して SoftwareBitmap をスケールアップする方法を示しています。 この例は、VSR API の一般的な使用方法を表していません。 Direct3D を使用するよりもパフォーマンスが低くなります。 ただし、この例を使用して、カメラまたはビデオ ストリーミング パイプラインを設定せずに VSR API を試すことができます。 ImageBuffer を使用する場合、ビデオ スケーラーには BGR8 が必要であるため、提供された SoftwareBitmap のピクセル形式を変換するには、いくつかのヘルパー メソッドが必要です。
この記事のコード例は、Windows AI API サンプルの VSR コンポーネントに基づいています
public SoftwareBitmap ScaleVideoFrame(SoftwareBitmap inputFrame)
{
ImageBuffer inputImageBuffer = SoftwareBitmapExtensions.ConvertToBgr8ImageBuffer(inputFrame);
var size = (uint)(inputFrame.PixelWidth * inputFrame.PixelHeight * 3);
IBuffer outputBuffer = new global::Windows.Storage.Streams.Buffer(size);
outputBuffer.Length = size;
ImageBuffer outputImageBuffer = ImageBuffer.CreateForBuffer(
outputBuffer,
ImageBufferPixelFormat.Bgr8,
inputFrame.PixelWidth,
inputFrame.PixelHeight,
inputFrame.PixelWidth * 3);
var result = _videoScaler!.ScaleImageBuffer(inputImageBuffer, outputImageBuffer, new VideoScalerOptions());
if (result.Status != VideoScalerStatus.Success)
{
throw new Exception($"Failed to scale video frame: {result.Status}");
}
return SoftwareBitmapExtensions.ConvertBgr8ImageBufferToBgra8SoftwareBitmap(outputImageBuffer);
}
ソフトウェア ビットマップ拡張メソッド
次のヘルパーメソッドは、SoftwareBitmap を BGRA8 形式と BGR8 形式の間で、ビデオスカラーの入力要件と出力要件に合わせて変換します。
public static ImageBuffer ConvertToBgr8ImageBuffer(SoftwareBitmap input)
{
var bgraBitmap = input;
if (input.BitmapPixelFormat != BitmapPixelFormat.Bgra8)
{
bgraBitmap = SoftwareBitmap.Convert(input, BitmapPixelFormat.Bgra8, BitmapAlphaMode.Premultiplied);
}
int width = bgraBitmap.PixelWidth;
int height = bgraBitmap.PixelHeight;
byte[] bgraBuffer = new byte[width * height * 4];
bgraBitmap.CopyToBuffer(bgraBuffer.AsBuffer());
byte[] bgrBuffer = new byte[width * height * 3];
for (int i = 0, j = 0; i < bgraBuffer.Length; i += 4, j += 3)
{
bgrBuffer[j] = bgraBuffer[i];
bgrBuffer[j + 1] = bgraBuffer[i + 1];
bgrBuffer[j + 2] = bgraBuffer[i + 2];
}
return ImageBuffer.CreateForBuffer(
bgrBuffer.AsBuffer(),
ImageBufferPixelFormat.Bgr8,
width,
height,
width * 3);
}
public static SoftwareBitmap ConvertBgr8ImageBufferToBgra8SoftwareBitmap(ImageBuffer bgrImageBuffer)
{
if (bgrImageBuffer.PixelFormat != ImageBufferPixelFormat.Bgr8)
{
throw new ArgumentException("Input ImageBuffer must be in Bgr8 format");
}
int width = bgrImageBuffer.PixelWidth;
int height = bgrImageBuffer.PixelHeight;
// Get BGR data from ImageBuffer
byte[] bgrBuffer = new byte[width * height * 3];
bgrImageBuffer.CopyToByteArray(bgrBuffer);
// Create BGRA buffer (4 bytes per pixel)
byte[] bgraBuffer = new byte[width * height * 4];
for (int i = 0, j = 0; i < bgrBuffer.Length; i += 3, j += 4)
{
bgraBuffer[j] = bgrBuffer[i]; // B
bgraBuffer[j + 1] = bgrBuffer[i + 1]; // G
bgraBuffer[j + 2] = bgrBuffer[i + 2]; // R
bgraBuffer[j + 3] = 255; // A (full opacity)
}
// Create SoftwareBitmap and copy data
var softwareBitmap = new SoftwareBitmap(
BitmapPixelFormat.Bgra8,
width,
height,
BitmapAlphaMode.Premultiplied);
softwareBitmap.CopyFromBuffer(bgraBuffer.AsBuffer());
return softwareBitmap;
}
責任ある AI
Microsoft の責任ある AI 標準で説明されている主要な原則とプラクティスに従って、これらの API が信頼でき、安全で、責任を持って構築されていることを確認しました。 アプリに AI 機能を実装する方法の詳細については、 Windows での責任ある生成型 AI 開発に関するページを参照してください。
これらの VSR API は Machine Learning (ML) モデルを使用し、ビデオ通話や会議アプリなどのシナリオや、人の顔を話すソーシャルビデオや短い形式のビデオに特化して設計されています。 そのため、次のシナリオでは、これらの API をビデオに使用することはお勧めしません。
- ビデオに潜在的に機密性の高いコンテンツやアップスケーリングが含まれている場合、個人、文化的シンボル、宗教的なシンボルの映像など、誤解を招くような詳細やアイデンティティや顔の特徴を変更する可能性があります。
- 医療画像、法的証拠、法医学的証拠、本人確認など、忠実で変更されていないビデオが重要な場合。