Condividi tramite


Effetti per l'acquisizione di video

Questo argomento illustra come applicare effetti all'anteprima della fotocamera e registrare flussi video e illustra come usare l'effetto di stabilizzazione video.

Nota

Questo articolo si basa sui concetti e sul codice descritti in Acquisizione di foto, video e audio di base con MediaCapture, che descrive i passaggi necessari per implementare l'acquisizione di foto e video di base. È consigliabile acquisire familiarità con il modello di acquisizione multimediale di base in questo articolo prima di passare a scenari di acquisizione più avanzati. Il codice in questo articolo presuppone che l'app abbia già un'istanza di MediaCapture che è stata inizializzata correttamente.

Aggiunta e rimozione di effetti dal flusso video della fotocamera

Per acquisire o visualizzare in anteprima video dalla fotocamera del dispositivo, usare l'oggetto MediaCapture come descritto in Acquisizione di foto, video e audio di base con MediaCapture. Dopo aver inizializzato l'oggetto MediaCapture, è possibile aggiungere uno o più effetti video al flusso di anteprima o di acquisizione chiamando AddVideoEffectAsync, passando in un oggetto IVideoEffectDefinition che rappresenta l'effetto da aggiungere e un membro dell'enumerazione MediaStreamType che indica se l'effetto deve essere aggiunto al flusso di anteprima della fotocamera o al flusso di record.

Nota

In alcuni dispositivi, il flusso di anteprima e il flusso di acquisizione sono gli stessi, il che significa che se si specifica MediaStreamType.VideoPreview o MediaStreamType.VideoRecord quando si chiama AddVideoEffectAsync, l'effetto verrà applicato sia ai flussi di anteprima che a quello dei record. È possibile determinare se i flussi di anteprima e di record sono uguali nel dispositivo corrente controllando la proprietà VideoDeviceCharacteristic dell'oggetto MediaCaptureSettings per l'oggetto MediaCapture. Se il valore di questa proprietà è VideoDeviceCharacteristic.AllStreamsIdentical o VideoDeviceCharacteristic.PreviewRecordStreamIdentical, i flussi sono uguali e qualsiasi effetto applicato e uno influirà sull'altro.

L'esempio seguente aggiunge un effetto sia all'anteprima della fotocamera che ai flussi di record. In questo esempio viene illustrato il controllo per verificare se i flussi di record e anteprima sono uguali.

if (mediaCapture.MediaCaptureSettings.VideoDeviceCharacteristic == VideoDeviceCharacteristic.AllStreamsIdentical ||
    mediaCapture.MediaCaptureSettings.VideoDeviceCharacteristic == VideoDeviceCharacteristic.PreviewRecordStreamsIdentical)
{
    // This effect will modify both the preview and the record streams, because they are the same stream.
    myRecordEffect = await mediaCapture.AddVideoEffectAsync(myEffectDefinition, MediaStreamType.VideoRecord);
}
else
{
    myRecordEffect = await mediaCapture.AddVideoEffectAsync(myEffectDefinition, MediaStreamType.VideoRecord);
    myPreviewEffect = await mediaCapture.AddVideoEffectAsync(myEffectDefinition, MediaStreamType.VideoPreview);
}

Si noti che AddVideoEffectAsync restituisce un oggetto che implementa IMediaExtension che rappresenta l'effetto video aggiunto. Alcuni effetti consentono di modificare le impostazioni dell'effetto passando un PropertySet nel metodo SetProperties.

A partire da Windows 10 versione 1607, puoi anche usare l'oggetto restituito da AddVideoEffectAsync per rimuovere l'effetto dalla pipeline video passandolo a RemoveEffectAsync. RemoveEffectAsync determina automaticamente se il parametro dell'oggetto effetto è stato aggiunto al flusso di anteprima o di record, quindi non è necessario specificare il tipo di flusso quando si effettua la chiamata.

if (myRecordEffect != null)
{
    await mediaCapture.RemoveEffectAsync(myRecordEffect);
}
if(myPreviewEffect != null)
{
    await mediaCapture.RemoveEffectAsync(myPreviewEffect);
}

È anche possibile rimuovere tutti gli effetti dal flusso di anteprima o acquisizione chiamando ClearEffectsAsync e specificando il flusso per cui rimuovere tutti gli effetti.

await mediaCapture.ClearEffectsAsync(MediaStreamType.VideoPreview);
await mediaCapture.ClearEffectsAsync(MediaStreamType.VideoRecord);

Effetto di stabilizzazione video

L'effetto di stabilizzazione video manipola i fotogrammi di un flusso video per ridurre al minimo lo scuotimento causato dal dispositivo di acquisizione nella mano. Poiché questa tecnica fa sì che i pixel vengano spostati verso destra, sinistra, su e giù e perché l'effetto non è in grado di sapere qual è il contenuto appena esterno al fotogramma video, il video stabilizzato viene ritagliato leggermente dal video originale. Viene fornita una funzione utility per consentire di regolare le impostazioni di codifica video per gestire in modo ottimale il ritaglio eseguito dall'effetto.

Nei dispositivi che lo supportano, la stabilizzazione ottica delle immagini (OIS) stabilizza il video modificando meccanicamente il dispositivo di acquisizione e, pertanto, non è necessario ritagliare i bordi dei fotogrammi video. Per altre informazioni, vedere Acquisire i controlli del dispositivo per l'acquisizione di video.

Configurare l'app per l'uso della stabilizzazione video

Oltre agli spazi dei nomi necessari per l'acquisizione multimediale di base, l'uso dell'effetto di stabilizzazione video richiede lo spazio dei nomi seguente.

using Windows.Media.Core;
using Windows.Media.MediaProperties;
using Windows.Media.Effects;
using Windows.Media;

Dichiarare una variabile membro per archiviare l'oggetto VideoStabilizationEffect. Come parte dell'implementazione dell'effetto, modificherai le proprietà di codifica usate per codificare il video acquisito. Dichiarare due variabili per archiviare una copia di backup delle proprietà di codifica di input e output iniziali in modo da poterle ripristinare in un secondo momento quando l'effetto è disabilitato. Infine, dichiarare una variabile membro di tipo MediaEncodingProfile perché questo oggetto sarà accessibile da più posizioni all'interno del codice.

private VideoStabilizationEffect _videoStabilizationEffect;
private VideoEncodingProperties _inputPropertiesBackup;
private VideoEncodingProperties _outputPropertiesBackup;
private MediaEncodingProfile _encodingProfile;

Per questo scenario, è necessario assegnare l'oggetto profilo di codifica multimediale a una variabile membro in modo che sia possibile accedervi in un secondo momento.

_encodingProfile = MediaEncodingProfile.CreateMp4(VideoEncodingQuality.Auto);

Inizializzare l'effetto di stabilizzazione video

Dopo l'inizializzazione dell'oggetto MediaCapture, creare una nuova istanza dell'oggetto VideoStabilizationEffectDefinition. Chiamare MediaCapture.AddVideoEffectAsync per aggiungere l'effetto alla pipeline video e recuperare un'istanza della classe VideoStabilizationEffect. Specificare MediaStreamType.VideoRecord per indicare che l'effetto deve essere applicato al flusso di record video.

Registrare un gestore eventi per l'evento EnabledChanged e chiamare il metodo helper SetUpVideoStabilizationRecommendationAsync, entrambi descritti più avanti in questo articolo. Impostare infine la proprietà enabled dell'effetto su true per abilitare l'effetto.

// Create the effect definition
VideoStabilizationEffectDefinition stabilizerDefinition = new VideoStabilizationEffectDefinition();

// Add the video stabilization effect to media capture
_videoStabilizationEffect =
    (VideoStabilizationEffect)await mediaCapture.AddVideoEffectAsync(stabilizerDefinition, MediaStreamType.VideoRecord);

_videoStabilizationEffect.EnabledChanged += VideoStabilizationEffect_EnabledChanged;

await SetUpVideoStabilizationRecommendationAsync();

_videoStabilizationEffect.Enabled = true;

Come descritto in precedenza in questo articolo, la tecnica usata dall'effetto di stabilizzazione video comporta necessariamente il ritaglio del video stabilizzato leggermente dal video di origine. Definire la funzione helper seguente nel codice per regolare le proprietà di codifica video per gestire in modo ottimale questa limitazione dell'effetto. Questo passaggio non è necessario per usare l'effetto di stabilizzazione video, ma se non si esegue questo passaggio, il video risultante verrà leggermente ottimizzato e pertanto avrà una fedeltà visiva leggermente inferiore.

Chiamare GetRecommendedStreamConfiguration nell'istanza dell'effetto di stabilizzazione video, passando l'oggetto VideoDeviceController, che informa l'effetto sulle proprietà di codifica del flusso di input corrente e MediaEncodingProfile che consente di conoscere le proprietà di codifica di output correnti. Questo metodo restituisce un oggetto VideoStreamConfiguration contenente le nuove proprietà di codifica del flusso di input e output consigliate.

Le proprietà di codifica di input consigliate sono, se supportate dal dispositivo, una risoluzione superiore fornita dalle impostazioni iniziali in modo che si verifichi una perdita minima di risoluzione dopo l'applicazione del ritaglio dell'effetto.

Chiamare VideoDeviceController.SetMediaStreamPropertiesAsync per impostare le nuove proprietà di codifica. Prima di impostare le nuove proprietà, usare la variabile membro per archiviare le proprietà di codifica iniziali in modo da poter modificare di nuovo le impostazioni quando si disabilita l'effetto.

Se l'effetto di stabilizzazione video deve ritagliare il video di output, le proprietà di codifica di output consigliate saranno le dimensioni del video ritagliato. Ciò significa che la risoluzione di output corrisponderà alle dimensioni del video ritagliato. Se non si usano le proprietà di output consigliate, il video verrà ridimensionato in modo da corrispondere alle dimensioni di output iniziali, con conseguente perdita di fedeltà visiva.

Impostare la proprietà Video dell'oggetto MediaEncodingProfile. Prima di impostare le nuove proprietà, usare la variabile membro per archiviare le proprietà di codifica iniziali in modo da poter modificare di nuovo le impostazioni quando si disabilita l'effetto.

private async Task SetUpVideoStabilizationRecommendationAsync()
{

    // Get the recommendation from the effect based on our current input and output configuration
    var recommendation = _videoStabilizationEffect.GetRecommendedStreamConfiguration(mediaCapture.VideoDeviceController, _encodingProfile.Video);

    // Handle the recommendation for the input into the effect, which can contain a larger resolution than currently configured, so cropping is minimized
    if (recommendation.InputProperties != null)
    {
        // Back up the current input properties from before VS was activated
        _inputPropertiesBackup = mediaCapture.VideoDeviceController.GetMediaStreamProperties(MediaStreamType.VideoRecord) as VideoEncodingProperties;

        // Set the recommendation from the effect (a resolution higher than the current one to allow for cropping) on the input
        await mediaCapture.VideoDeviceController.SetMediaStreamPropertiesAsync(MediaStreamType.VideoRecord, recommendation.InputProperties);
        await mediaCapture.VideoDeviceController.SetMediaStreamPropertiesAsync(MediaStreamType.VideoPreview, recommendation.InputProperties);
    }

    // Handle the recommendations for the output from the effect
    if (recommendation.OutputProperties != null)
    {
        // Back up the current output properties from before VS was activated
        _outputPropertiesBackup = _encodingProfile.Video;

        // Apply the recommended encoding profile for the output
        _encodingProfile.Video = recommendation.OutputProperties;
    }
}

Gestire l'effetto di stabilizzazione video disabilitato

Il sistema può disabilitare automaticamente l'effetto di stabilizzazione video se la velocità effettiva pixel è troppo elevata per gestire l'effetto o se rileva che l'effetto è in esecuzione lentamente. In questo caso, viene generato l'evento EnabledChanged. L'istanza VideoStabilizationEffect nel parametro sender indica il nuovo stato dell'effetto, abilitato o disabilitato. VideoStabilizationEffectEnabledChangedEventArgs ha un valore VideoStabilizationEffectEnabledChangedReasonche indica il motivo per cui l'effetto è stato abilitato o disabilitato. Si noti che questo evento viene generato anche se si abilita o disabilita l'effetto a livello di codice, nel qual caso il motivo sarà Programmatico.

In genere, si può usare questo evento per regolare l'interfaccia utente dell'app per indicare lo stato corrente della stabilizzazione video.

private async void VideoStabilizationEffect_EnabledChanged(VideoStabilizationEffect sender, VideoStabilizationEffectEnabledChangedEventArgs args)
{
    await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
    {
        // Update your UI to reflect the change in status
        ShowMessageToUser("video stabilization status: " + sender.Enabled + ". Reason: " + args.Reason);
    });
}

Pulire l'effetto di stabilizzazione video

Per pulire l'effetto di stabilizzazione video, chiamare RemoveEffectAsync per rimuovere l'effetto dalla pipeline video. Se le variabili membro contenenti le proprietà di codifica iniziali non sono null, usarle per ripristinare le proprietà di codifica. Rimuovere infine il gestore eventi EnabledChanged e impostare l'effetto su null.

// Clear all effects in the pipeline
await mediaCapture.RemoveEffectAsync(_videoStabilizationEffect);

// If backed up settings (stream properties and encoding profile) exist, restore them and clear the backups
if (_inputPropertiesBackup != null)
{
    await mediaCapture.VideoDeviceController.SetMediaStreamPropertiesAsync(MediaStreamType.VideoRecord, _inputPropertiesBackup);
    _inputPropertiesBackup = null;
}

if (_outputPropertiesBackup != null)
{
    _encodingProfile.Video = _outputPropertiesBackup;
    _outputPropertiesBackup = null;
}

_videoStabilizationEffect.EnabledChanged -= VideoStabilizationEffect_EnabledChanged;

_videoStabilizationEffect = null;