Sprache

Erste Schritte mit AI Video Super Resolution (VSR)

Video Super Resolution (VSR) ist eine KI-basierte Video-Up-Sampling-Technologie, mit der Videodatenströme mit niedriger Auflösung von Personen intelligent hochskaliert werden, Schärfe und Details wiederhergestellt werden, die andernfalls aufgrund von Bandbreitenbeschränkungen, schlechten Netzwerkbedingungen, Komprimierung oder Inhalten mit niedrigerer Qualität verloren gehen würden.

Das Hinzufügen von VSR-Funktionen zu Ihrer App ermöglicht Szenarien wie die folgenden:

  • Verbessern der Videoqualität über schlechte Netzwerkverbindungen
  • Bandbreitenoptimierung zur Reduzierung der CDN-Kosten
  • Szenarien mit hoher Bandbreite wie Gruppenvideoanrufe mit mehreren Teilnehmern
  • Verbessern der Videoqualität in sozialen Medien beim Bearbeiten, Hochladen oder Anzeigen

Die VSR-Funktion ist auf Copilot+ PCs mit einer NPU und auf Geräten verfügbar, die die empfohlenen CPU-Spezifikationen erfüllen. Weitere Informationen finden Sie unter Entwickeln von KI-Anwendungen für Copilot+ PCs und in der Tabelle der unterstützten Hardware.

Unterstützte Hardware

Gerätetechnik Status Details
NPU (Copilot+ PC) ✅ Verfügbar Beste Leistung. Weitere Informationen finden Sie im Entwicklerhandbuch Copilot+ PCs.
CPU ✅ Verfügbar Am besten auf Geräten, die die empfohlenen CPU-Spezifikationen erfüllen. VSR wird weiterhin versuchen, auf leistungsschwächeren Geräten zu laufen, aber Echtzeitqualität und Bildrate können darunter leiden.
Grafikprozessor (GPU) ❌ Nicht unterstützt VSR ist auf GPU nicht verfügbar.

Note

Die Hardwareauswahl erfolgt automatisch. Auf einem Copilot+ PC mit einer NPU wird VSR immer auf der NPU ausgeführt. Auf Nicht-Copilot+-Geräten wird VSR automatisch auf der CPU ausgeführt – es gibt keinen Entwickler oder Endbenutzer, der die CPU auf einem Copilot+ Gerät auswählt. Dies entspricht dem Muster, das von anderen Windows AI-APIs verwendet wird; siehe Supported Hardware für die apiübergreifende Ansicht.

Diese VSR-APIs verwenden Machine Learning (ML)-Modelle und wurden speziell für Szenarien wie Videoanruf- und Konferenz-Apps sowie soziale Netzwerke und Kurzvideos entwickelt, die menschliche Gesichter beim Sprechen zeigen.

VSR unterstützt derzeit die folgenden Auflösungs-, Format- und FPS-Bereiche:

Merkmal Unterstützte Inhalte
Eingabeauflösung 240p – 1440p
Ausgabeauflösung 480p – 1440p (4K für die Offline-Videoverarbeitung)
Bilder pro Sekunde (FPS)-Bereich 15 fps – 60 fps
Eingabepixelformat BGR (ImageBuffer-API), NV12 (Direct3D-API)
Ausgabepixelformat BGR (ImageBuffer-API), BGRA und NV12 (Direct3D-API)

Das VSR-Modell wird als Teil der Windows App SDK bereitgestellt, sodass es keinen separaten Download- oder Erstausführungs-Zustimmungsschritt auf CPU-Geräten gibt. VSR läuft auf jeder CPU, auf der auch die übrigen Windows AI-APIs laufen, aber die Qualität der Echtzeitskalierung und die Bildfrequenz hängen von der Host-CPU ab.

Für eine gute CPU-Leistung sollten Zielgeräte alle der folgenden empfohlenen Spezifikationen erfüllen:

  • 4 oder mehr physische Kerne
  • 3 GHz oder höherer Basistakt
  • 32 MB oder mehr L3-Cache

Dies sind Empfehlungen, keine harten Mindestwerte – die API versucht weiterhin, auf Geräten mit niedrigerer Spezifikation zu skalieren. Apps, die auf einen breiten CPU-Bereich abzielen, sollten die CPU zur Laufzeit abfragen und, wenn das Gerät unter den empfohlenen Wert fällt, auf eine Nicht-VSR-Pipeline zurückgreifen oder dem Benutzer einen Hinweis auf einen Qualitätskompromiss anzeigen.

Note

GetReadyState und die CPU-Spezifikationsprüfung beantwortet verschiedene Fragen und sollte zusammen verwendet werden. GetReadyState gibt an, ob VSR auf dem Gerät überhaupt unterstützt wird (das Modell ist geladen, Treiber sind vorhanden, die Hardwarerichtlinie erlaubt es). Die CPU-Spezifikationsüberprüfung teilt Ihnen mit, ob VSR gut genug für Ihre UX ausgeführt wird. Verwenden Sie GetReadyState, um zu entscheiden, ob VSR aufgerufen werden soll. Verwenden Sie die CPU-Überprüfung, um bei grenzwertiger Hardware zwischen VSR und einem einfachen Fallback (z. B. bilineares Upscaling) zu entscheiden.

Überprüfen der CPU-Unterstützungsebene

Im folgenden C#-Beispiel werden Windows Management Instrumentation (WMI) verwendet, um die klasse Win32_Processor abzufragen und true zurückgibt, wenn das Gerät die empfohlenen Spezifikationen erfüllt. Im Beispiel wird das von Microsoft veröffentlichte System.Management NuGet-Paket verwendet – der .NET-Standardwrapper für WMI –, um aus C# auf WMI zuzugreifen.

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;
}

Verwenden Sie das Ergebnis, um UX-Entscheidungen entsprechend zu steuern – zeigen Sie beispielsweise einen Hinweis auf den Qualitätskompromiss an, legen Sie standardmäßig eine niedrigere Ausgabeauflösung fest oder verzichten Sie auf Geräten, die die Empfehlungen nicht erfüllen, ganz auf VSR.

Hinweise zur WMI-Prüfung

  • Zwischenspeichern Sie das Ergebnis. Die erste WMI-Abfrage dauert aufgrund der COM-Initialisierung etwa 50–200 ms. Nachfolgende Abfragen sind schnell, aber das sauberste Muster besteht darin, einmal beim Start auszuführen MeetsRecommendedCpuSpecs und den booleschen Wert für die Lebensdauer des Prozesses zwischenzuspeichern. CPU-Hardware ändert sich zur Laufzeit nicht.
  • MaxClockSpeed ist der nominelle Basistakt, nicht der Boost-Takt. Eine 2,5-GHz-CPU, die auf 4,5 GHz hochtaktet, meldet 2500 und besteht die 3-GHz-Prüfung nicht. Dies ist beabsichtigt – für Streaming-KI-Workloads wie VSR ist ein dauerhaft hoher Durchsatz wichtiger als ein kurzzeitiger Boost-Takt, daher ist der Basistakt hier das richtige Signal.
  • Alternative für Unter millisekundenprüfungen. Wenn Sie die Abhängigkeit System.Management vermeiden müssen oder die WMI-Kosten inakzeptabel sind (z. B. auf einem hot startup path), sind dieselben Daten über systemeigene Windows-APIs verfügbar: GetLogicalProcessorInformationEx gibt Kernanzahlen und Cachegrößen zurück, und die bewertete Taktgeschwindigkeit wird bei HKLM\HARDWARE\DESCRIPTION\System\CentralProcessor\0 (~MHz Wert) verfügbar gemacht. Diese liefern Ergebnisse in weniger als einer Millisekunde, erfordern jedoch mehr Code.

Eine VideoScaler-Sitzung erstellen

Das folgende Beispiel zeigt, wie Eine VSR-Sitzung erstellt wird. Rufen Sie zunächst eine Instanz von ExecutionProviderCatalog ab, und rufen Sie "EnsureAndRegisterCertifiedAsync " auf, um die verfügbaren Modelle zu laden. Rufen Sie GetReadyState in der VideoScaler-Klasse auf, um zu ermitteln, ob der Videoskaler bereit für die Verarbeitung von Frames ist. Wenn nicht, rufen Sie EnsureReadyAsync auf, um den Videoskaler zu initialisieren.

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();
}

Skalieren eines Videoframes

Im folgenden Codebeispiel wird die VideoScaler.Scale-Methode verwendet, um Bilddaten in einem VideoFrame-Objekt zu verkleineren. Mit der MediaFrameReader-Klasse können Sie VideoFrame von einer Kamera abrufen. Weitere Informationen finden Sie unter Verarbeiten von Medienframes mit MediaFrameReader. Sie können auch das WinUI Community Toolkit CameraPreview-Steuerelement verwenden, um VideoFrame-Objekte von der Kamera abzurufen.

Als Nächstes wird eine Direct3DSurface aus dem Eingabevideoframe abgerufen, und eine weitere Direct3DSurface wird für die Ausgabe des Upscaling-Prozesses erstellt. VideoScaler.Scale wird aufgerufen, um den Frame zu vergrößern. In diesem Beispiel wird ein Bildsteuerelement in der Benutzeroberfläche der App mit dem hochskalierten Frame aktualisiert.

 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;
        }
    });
}

Skalieren einer SoftwareBitmap mit ImageBuffer

Im folgenden Codebeispiel wird die Verwendung der VideoScaler-Klasse zum Hochskalieren einer SoftwareBitmap veranschaulicht. Dieses Beispiel stellt keine typische Verwendung der VSR-APIs dar. Es ist weniger leistungsfähig als Direct3D. Sie können dieses Beispiel jedoch verwenden, um mit den VSR-APIs zu experimentieren, ohne eine Kamera- oder Videostreamingpipeline einzurichten. Da für die Videoskalierung bei Verwendung eines ImageBuffers ein BGR8 erforderlich ist, sind einige Hilfsmethoden erforderlich, um das Pixelformat der bereitgestellten SoftwareBitmap zu konvertieren.

Der Beispielcode in diesem Artikel basiert auf der VSR-Komponente der Windows AI-API-Beispiele.

    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);
    }

Software-Bitmaperweiterungsmethoden

Die folgenden Hilfsmethoden konvertieren ein SoftwareBitmap-Format zwischen BGRA8 - und BGR8-Formaten , um den Eingabe- und Ausgabeanforderungen des Videoskakalers zu entsprechen.

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;
    }

Verantwortungsvolle KI

Wir haben die wichtigsten Prinzipien und Praktiken befolgt, die in den Microsoft Responsible AI Standards beschrieben werden, um sicherzustellen, dass diese APIs vertrauenswürdig, sicher und verantwortungsbewusst erstellt werden. Weitere Informationen zur Implementierung von KI-Features in Ihrer App finden Sie unter Verantwortlicher generativer KI-Entwicklung unter Windows.

Diese VSR-APIs verwenden Modelle des Maschinellen Lernens (ML), die speziell für Szenarien wie Videoanruf- und Konferenz-Apps sowie soziale und Kurzform-Videos entwickelt wurden, die menschliche Gesichter zeigen, die sprechen. Daher wird die Verwendung dieser APIs für Videos in den folgenden Szenarien nicht empfohlen:

  • Wenn das Video potenziell sensible Inhalte und Upscaling enthält, könnten irreführende Details oder Gesichtsmerkmale wie Filmmaterial von Einzelpersonen, kulturelle Symbole oder religiöse Symbole eingeführt werden.
  • Wenn getreues, unverändertes Video kritisch ist, z. B. für medizinische Bildgebung, juristische oder forensische Beweise oder Identitätsüberprüfung.

Siehe auch