

# SDK di trasmissione IVS \$1 Streaming a bassa latenza
<a name="broadcast"></a>

L'SDK di trasmissione a bassa latenza di IVS) è rivolto agli sviluppatori che creano applicazioni con Amazon IVS. Questo SDK è progettato per trarre vantaggio dall'architettura di Amazon IVS e, così come Amazon IVS, vedrà l'introduzione di miglioramenti continui e nuove funzionalità. Essendo un SDK di trasmissione nativo, è progettato per ridurre al minimo l'impatto sulle prestazioni dell'applicazione e dei dispositivi utilizzati dagli utenti per accedere all'applicazione.

L'applicazione può avvalersi delle funzionalità principali dell'SDK di trasmissione Amazon IVS:
+ **Streaming di alta qualità** - L'SDK di trasmissione supporta lo streaming di alta qualità. Catturare video dalla fotocamera e utilizzare la codifica fino a 1080p per un'esperienza visiva di alta qualità.
+ **Regolazioni automatiche del bitrate** - Gli utenti di smartphone sono mobili, quindi le loro condizioni di rete possono cambiare nel corso della trasmissione. L'SDK di trasmissione di Amazon IVS regola automaticamente il bitrate video per adattarsi alle mutevoli condizioni di rete.
+ **Supporto per l'orientamento verticale e orizzontale** - Indipendentemente dal modo in cui gli utenti tengono in mano i dispositivi, l'immagine viene visualizzata e ridimensionata correttamente. L'SDK di trasmissione supporta ogni dimensione del riquadro, sia in verticale che in orizzontale. Gestisce automaticamente le sue proporzioni quando gli utenti ruotano il dispositivo e cambiano l'orientamento configurato.
+ **Streaming sicuro** - Le trasmissioni dell'utente sono crittografate tramite TLS, in modo che possano mantenere protetti i propri flussi.
+ **Dispositivi audio esterni** - L'SDK di trasmissione Amazon IVS supporta collegamenti audio con cavo, USB e microfoni esterni Bluetooth SCO.

## Requisiti della piattaforma
<a name="broadcast-platform-requirements"></a>

### Piattaforme native
<a name="broadcast-native-platforms"></a>


| Piattaforma | Versioni supportate | 
| --- | --- | 
| Android |  6.0 e versioni successive  | 
| iOS |  14\$1  Se per la propria applicazione la trasmissione è essenziale, specificare Metal come requisito per scaricare l'app dall'App Store di Apple utilizzando [UIRequiredDeviceCapabilities](https://developer.apple.com/documentation/bundleresources/information_property_list/uirequireddevicecapabilities).   | 

IVS supporta un minimo di 4 versioni principali di iOS e 6 versioni principali di Android. Il nostro supporto per le versioni correnti potrebbe estendersi oltre questi minimi. I clienti verranno avvisati tramite note di rilascio dell'SDK con almeno 3 mesi di anticipo se una versione principale non è più supportata.

### Browser desktop
<a name="browser-desktop"></a>


| Browser | Piattaforme supportate | Versioni supportate | 
| --- | --- | --- | 
| Chrome | Windows, macOS | Due versioni principali (versione corrente e precedente più recente) | 
| Firefox | Windows, macOS | Due versioni principali (versione corrente e precedente più recente) | 
| Edge | Windows 8.1 e versioni successive | Due versioni principali (versione corrente e precedente più recente) Esclude Edge Legacy | 
| Safari | macOS | Due versioni principali (versione corrente e precedente più recente) | 

### Browser per dispositivi mobili
<a name="browser-mobile"></a>


| Browser | Versioni supportate | 
| --- | --- | 
| Chrome per iOS, Safari per iOS |  Due versioni principali (versione corrente e precedente più recente)  | 
| Chrome per iPadOS, Safari per iPadOS |  Due versioni principali (versione corrente e precedente più recente)  | 
| Chrome per Android | Due versioni principali (versione corrente e precedente più recente)  | 

## Viste Web
<a name="broadcast-webviews"></a>

L'SDK di trasmissione Web non fornisce supporto per visualizzazioni Web o ambienti simili al Web (TV, console e così via). Per le implementazioni mobili, consulta la Guida all'SDK di trasmissione in streaming a bassa latenza per [Android](broadcast-android.md) e [iOS](broadcast-ios.md).

## Richiesta di accesso al dispositivo
<a name="broadcast-device-access"></a>

L'SDK di trasmissione richiede l'accesso alle fotocamere e ai microfoni del dispositivo, sia quelli integrati nel dispositivo che quelli collegati tramite Bluetooth, USB o ingresso audio.

## Supporto
<a name="broadcast-support"></a>

Se si verifica un errore di trasmissione o un altro problema con il flusso, determinare l'identificatore univoco della sessione di riproduzione tramite l'API di trasmissione. 


| Per questo SDK di trasmissione di Amazon IVS: | Usare questo: | 
| --- | --- | 
| Android | Funzione `getSessionId` su `BroadcastSession`  | 
| iOS | `sessionId` Proprietà di `IVSBroadcastSession`  | 
| App | `getSessionId`Funzione  | 

Condividere questo identificatore di sessione di trasmissione con AWS Support. Grazie a questo identificatore, si possono ottenere informazioni utili per risolvere il problema.

**Nota:** l'SDK di trasmissione viene continuamente migliorato. Consultare le [Note di rilascio di Amazon IVS](release-notes.md)per le versioni disponibili e i problemi risolti. Se necessario, prima di contattare il supporto, aggiornare la versione dell'SDK di trasmissione e verificare se il problema è stato risolto.

### Controllo delle versioni
<a name="broadcast-support-versioning"></a>

Gli SDK di trasmissione di Amazon IVS utilizzano il [controllo semantico delle versioni](https://semver.org/).

Per questa discussione, supponiamo che:
+ La versione più recente sia la 4.1.3.
+ L'ultima versione della versione principale precedente sia 3.2.4.
+ La versione più recente della versione 1.x sia la 1.5.6.

Le nuove funzionalità compatibili con le versioni precedenti vengono aggiunte come versioni secondarie dell'ultima versione. In questo caso, il set successivo di nuove funzionalità verrà aggiunto come versione 4.2.0.

Le correzioni di bug minori compatibili con le versioni precedenti vengono aggiunte come versioni di patch dell'ultima versione. Nel nostro caso, il set di correzioni minori di bug successivo sarà aggiunto come versione 4.1.4.

Le correzioni di bug principali compatibili con le versioni precedenti sono gestite in modo diverso, ovvero vengono aggiunte alle diverse versioni:
+ Rilascio della patch dell'ultima versione. Nel nostro caso, questa è la versione 4.1.4.
+ Rilascio della patch della versione secondaria precedente. Nel nostro caso, questa è la versione 3.2.5.
+ Rilascio di patch dell'ultima versione 1.x. Nel nostro caso, questa è la versione 1.5.7.

Le correzioni di bug principali sono definite dal team di prodotti Amazon IVS. Esempi tipici sono gli aggiornamenti critici della sicurezza e alcune altre correzioni necessarie per i clienti.

**Nota:** negli esempi precedenti, le versioni rilasciate vengono incrementate senza saltare alcun numero (ad esempio, da 4.1.3 a 4.1.4). In realtà, uno o più numeri di patch possono rimanere interni e non essere rilasciati, quindi la versione rilasciata potrebbe aumentare da 4.1.3 a, ad esempio, 4.1.6.

# SDK di trasmissione IVS: guida per il web \$1 Streaming a bassa latenza
<a name="broadcast-web"></a>

L'SDK di trasmissione Web a bassa latenza di IV) offre agli sviluppatori gli strumenti per creare esperienze interattive e in tempo reale sul Web.

**Ultima versione dell'SDK di trasmissione Web:** 1.33.0 ([Note di rilascio](https://docs.aws.amazon.com/ivs/latest/LowLatencyUserGuide/release-notes.html#mar12-25-broadcast-web-ll)) 

**Documentazione di riferimento:** per informazioni sui metodi più importanti disponibili nell'SDK di trasmissione Web di Amazon IVS, consulta la documentazione di riferimento all'indirizzo [https://aws.github.io/amazon-ivs-web-broadcast/docs/sdk-reference](https://aws.github.io/amazon-ivs-web-broadcast/docs/sdk-reference). Assicurati che sia selezionata la versione più recente dell'SDK.

**Codice di esempio**: gli esempi seguenti sono un buon punto di partenza per iniziare a utilizzare rapidamente l'SDK:
+ [Trasmissione singola su un canale IVS (HTML e JavaScript)](https://codepen.io/amazon-ivs/pen/poLRoPp)
+ [Trasmissione singola con condivisione dello schermo su un canale IVS](https://stream.ivs.rocks/) ([React Source Code](https://github.com/aws-samples/amazon-ivs-broadcast-web-demo))

**Requisiti della piattaforma:** consulta [SDK di trasmissione Amazon IVS](https://docs.aws.amazon.com//ivs/latest/LowLatencyUserGuide/broadcast.html) per un elenco delle piattaforme supportate.

# Guida introduttiva all'SDK di trasmissione IVS per il web \$1 Streaming a bassa latenza
<a name="broadcast-web-getting-started"></a>

Questo documento illustra i passaggi necessari per iniziare a utilizzare l'SDK di trasmissione per lo streaming a bassa latenza di Amazon IVS per il web.

## Installazione della libreria
<a name="broadcast-web-install"></a>

Tieni presente che IVSBroadcastClient sfrutta [reflect-metadata](https://www.npmjs.com/package/reflect-metadata), che estende l'oggetto Reflect globale. Sebbene ciò non dovrebbe creare conflitti, possono esserci rari casi in cui potrebbe causare comportamenti indesiderati.

### Utilizzo di un tag di script
<a name="broadcast-web-how-to-install-script"></a>

L'SDK di trasmissione Web è distribuito come libreria JavaScript e può essere recuperato all'indirizzo [https://web-broadcast.live-video.net/1.33.0/amazon-ivs-web-broadcast.js](https://web-broadcast.live-video.net/1.33.0/amazon-ivs-web-broadcast.js).

Quando viene caricata tramite il tag `<script>`, la libreria espone una variabile globale nell'ambito della finestra denominato `IVSBroadcastClient`.

### Utilizzo di npm
<a name="broadcast-web-how-to-install-npm"></a>

Per installare il pacchetto della `npm`:

```
npm install amazon-ivs-web-broadcast
```

Ora puoi accedere all'oggetto `IVSBroadcastClient` e inserire altri moduli e costanti come `Errors`, `BASIC_LANDSCAPE`:

```
import IVSBroadcastClient, {
   Errors,
   BASIC_LANDSCAPE
} from 'amazon-ivs-web-broadcast';
```

## Esempi
<a name="broadcast-web-samples"></a>

Per iniziare rapidamente, consulta gli esempi di seguito:
+ [Trasmissione singola su un canale IVS (HTML e JavaScript)](https://codepen.io/amazon-ivs/pen/poLRoPp)
+ [Trasmissione singola con condivisione dello schermo su un canale IVS](https://stream.ivs.rocks/) ([React Source Code](https://github.com/aws-samples/amazon-ivs-broadcast-web-demo))

## Creazione di un'istanza di AmazonIVSBroadcastClient
<a name="broadcast-web-instance"></a>

Per utilizzare la libreria, è necessario creare un'istanza del client. Puoi farlo richiamando il metodo`create` su `IVSBroadcastClient` con il parametro `streamConfig` (specificando i vincoli della trasmissione come risoluzione e frequenza dei fotogrammi). Puoi specificare l'endpoint di acquisizione durante la creazione del client oppure impostarlo all'avvio di un flusso.

L'endpoint di acquisizione è disponibile nella console AWS o può essere restituito dall'operazione CreateChannel (ad esempio UNIQUE\$1ID.global-contribute.live-video.net).

```
const client = IVSBroadcastClient.create({
   // Enter the desired stream configuration
   streamConfig: IVSBroadcastClient.BASIC_LANDSCAPE,
   // Enter the ingest endpoint from the AWS console or CreateChannel API
   ingestEndpoint: 'UNIQUE_ID.global-contribute.live-video.net',
});
```

Queste sono le configurazioni di streaming supportate più comuni. Le impostazioni predefinite sono `BASIC` fino a 480p e 1,5 Mb/s di bitrate, BASIC Full HD fino a 1080p e 3,5 Mb/s di bitrate e `STANDARD` (o `ADVANCED`) fino a 1080p e 8,5 Mb/s. Se lo desideri, puoi personalizzare il bitrate, la frequenza dei fotogrammi e la risoluzione. Per ulteriori informazioni, consulta [BroadcastClientConfig](https://aws.github.io/amazon-ivs-web-broadcast/docs/sdk-reference/interfaces/BroadcastClientConfig).

```
IVSBroadcastClient.BASIC_LANDSCAPE;
IVSBroadcastClient.BASIC_FULL_HD_LANDSCAPE;
IVSBroadcastClient.STANDARD_LANDSCAPE;
IVSBroadcastClient.BASIC_PORTRAIT;
IVSBroadcastClient.BASIC_FULL_HD_PORTRAIT;
IVSBroadcastClient.STANDARD_PORTRAIT;
```

Puoi importarli singolarmente se usi il pacchetto `npm`.

Nota: assicurati che la configurazione lato client sia in linea con il tipo di canale di backend. Ad esempio, se il tipo di canale è `STANDARD`, `streamConfig` deve essere impostato su uno dei valori `IVSBroadcastClient.STANDARD_*`. Se il tipo di canale è `ADVANCED`, dovrai impostare la configurazione manualmente come mostrato di seguito (usando `ADVANCED_HD` come esempio):

```
const client = IVSBroadcastClient.create({
   // Enter the custom stream configuration
   streamConfig: {
      maxResolution: {
         width: 1080,
         height: 1920,
     },
     maxFramerate: 30,
     /**
      * maxBitrate is measured in kbps
      */
     maxBitrate: 3500,
   },
   // Other configuration . . .
});
```

## Richiedere autorizzazioni
<a name="broadcast-web-request-permissions"></a>

L'app deve richiedere l'autorizzazione per accedere alla fotocamera e al microfono dell'utente e tale autorizzazione deve utilizzare HTTPS. (Questo non riguarda solo Amazon IVS, ma qualsiasi sito Web che abbia bisogno di accedere alle fotocamere e ai microfoni.)

Ecco un esempio di funzione che mostra come richiedere e ottenere le autorizzazioni per dispositivi audio e video:

```
async function handlePermissions() {
   let permissions = {
       audio: false,
       video: false,
   };
   try {
       const stream = await navigator.mediaDevices.getUserMedia({ video: true, audio: true });
       for (const track of stream.getTracks()) {
           track.stop();
       }
       permissions = { video: true, audio: true };
   } catch (err) {
       permissions = { video: false, audio: false };
       console.error(err.message);
   }
   // If we still don't have permissions after requesting them display the error message
   if (!permissions.video) {
       console.error('Failed to get video permissions.');
   } else if (!permissions.audio) {
       console.error('Failed to get audio permissions.');
   }
}
```

Per ulteriori informazioni, consulta l'[API delle autorizzazioni](https://developer.mozilla.org/en-US/docs/Web/API/Permissions_API) e [MediaDevices.getUserMedia()](https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia).

## Configurazione di un'anteprima dello streaming
<a name="broadcast-web-request-set-up-stream"></a>

Per visualizzare in anteprima ciò che verrà trasmesso, fornisci all'SDK un elemento `<canvas>`.

```
// where #preview is an existing <canvas> DOM element on your page
const previewEl = document.getElementById('preview');
client.attachPreview(previewEl);
```

## Elenco dei dispositivi disponibili
<a name="broadcast-web-request-list-devices"></a>

Per vedere quali dispositivi sono disponibili per l'acquisizione, interroga il metodo [MediaDevices.enumerateDevices()](https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/enumerateDevices) del browser:

```
const devices = await navigator.mediaDevices.enumerateDevices();
window.videoDevices = devices.filter((d) => d.kind === 'videoinput');
window.audioDevices = devices.filter((d) => d.kind === 'audioinput');
```

## Recupero di un MediaStream da un dispositivo
<a name="broadcast-web-retrieve-mediastream"></a>

Dopo aver acquisito l'elenco dei dispositivi disponibili, puoi recuperare un flusso da qualsiasi numero di dispositivi. Ad esempio, puoi utilizzare il metodo `getUserMedia()` per recuperare un flusso da una videocamera.

Se desideri specificare da quale dispositivo catturare lo streaming, puoi impostare esplicitamente il `deviceId` nella sezione `audio` o `video` dei vincoli del supporto. In alternativa, puoi omettere `deviceId` e fare in modo che gli utenti selezionino i propri dispositivi dal prompt del browser.

È inoltre possibile specificare una risoluzione ideale della fotocamera utilizzando i vincoli `width` e `height`. (Ulteriori informazioni su questi vincoli sono disponibili [qui](https://developer.mozilla.org/en-US/docs/Web/API/MediaTrackConstraints#properties_of_video_tracks).) L'SDK applica automaticamente i limiti di larghezza e altezza che corrispondono alla risoluzione massima di trasmissione; tuttavia, è una buona idea applicarli anche tu stesso in modo da essere certi che le proporzioni dell'aspetto della sorgente non vengano modificate dopo aver aggiunto la sorgente all'SDK.

```
const streamConfig = IVSBroadcastClient.BASIC_LANDSCAPE;
...
window.cameraStream = await navigator.mediaDevices.getUserMedia({
   video: {
       deviceId: window.videoDevices[0].deviceId,
       width: {
           ideal: streamConfig.maxResolution.width,
       },
       height: {
           ideal: streamConfig.maxResolution.height,
       },
   },
});
window.microphoneStream = await navigator.mediaDevices.getUserMedia({
   audio: { deviceId: window.audioDevices[0].deviceId },
});
```

## Aggiunta di un dispositivo a uno streaming
<a name="broadcast-web-add-device"></a>

Dopo aver acquisito il flusso, puoi aggiungere dispositivi al layout specificando un nome univoco (di seguito, questo è `camera1`) e la posizione della composizione (per il video). Ad esempio, specificando una webcam, aggiungi la sorgente video della webcam allo streaming di trasmissione.

Quando si specifica il dispositivo di ingresso video, è necessario specificare l'indice, che rappresenta il "livello" su cui si desidera trasmettere. Questo è sinonimo di modifica delle immagini o CSS, dove uno z-index rappresenta l'ordine dei livelli da renderizzare. Facoltativamente, puoi fornire una posizione che definisca le coordinate x/y (così come la dimensione) della sorgente del flusso.

Per i dettagli dei parametri, consulta [VideoComposition](https://aws.github.io/amazon-ivs-web-broadcast/docs/sdk-reference/interfaces/VideoComposition).

```
client.addVideoInputDevice(window.cameraStream, 'camera1', { index: 0 }); // only 'index' is required for the position parameter
client.addAudioInputDevice(window.microphoneStream, 'mic1');
```

## Avviare una trasmissione
<a name="broadcast-web-start-broadcast"></a>

Per avviare una trasmissione, fornisci la chiave di streaming per il tuo canale Amazon IVS:

```
client
   .startBroadcast(streamKey)
   .then((result) => {
       console.log('I am successfully broadcasting!');
   })
   .catch((error) => {
       console.error('Something drastically failed while broadcasting!', error);
   });
```

## Interrompere una trasmissione
<a name="broadcast-web-stop-broadcast"></a>

```
client.stopBroadcast();
```

## Scambio delle posizioni video
<a name="broadcast-web-swap-video-positions"></a>

Il client supporta lo scambio delle posizioni di composizione dei dispositivi video:

```
client.exchangeVideoDevicePositions('camera1', 'camera2');
```

## Mute Audio (Disattiva audio)
<a name="broadcast-web-muting-audio"></a>

Per disattivare l'audio, rimuovi il dispositivo audio che utilizza `removeAudioInputDevice` o imposta la proprietà `enabled` sulla traccia audio:

```
let audioStream = client.getAudioInputDevice(AUDIO_DEVICE_NAME);
audioStream.getAudioTracks()[0].enabled = false;
```

Dove `AUDIO_DEVICE_NAME` è il nome dato al dispositivo audio originale durante la chiamata `addAudioInputDevice()`.

Per riattivare l'audio:

```
let audioStream = client.getAudioInputDevice(AUDIO_DEVICE_NAME);
audioStream.getAudioTracks()[0].enabled = true;
```

## Nascondere il video
<a name="broadcast-web-hiding-video"></a>

Per nascondere il video, rimuovi il dispositivo video utilizzando `removeVideoInputDevice` o imposta la proprietà `enabled` sulla traccia video:

```
let videoStream = client.getVideoInputDevice(VIDEO_DEVICE_NAME).source;
videoStream.getVideoTracks()[0].enabled = false;
```

Dove `VIDEO_DEVICE_NAME` è il nome dato al dispositivo video durante la chiamata `addVideoInputDevice()` originale.

Per mostrare il video:

```
let videoStream = client.getVideoInputDevice(VIDEO_DEVICE_NAME).source;
videoStream.getVideoTracks()[0].enabled = true;
```

# Problemi noti e soluzioni alternative per l'SDK di trasmissione IVS per il web \$1 Streaming a bassa latenza
<a name="broadcast-web-known-issues"></a>

Questo documento elenca i problemi noti che potresti riscontrare durante l'utilizzo dell'SDK di trasmissione dello streaming a bassa latenza di Amazon IVS per il web e suggerisce possibili soluzioni alternative.
+ I visualizzatori potrebbero riscontrare artefatti verdi o framerate irregolare quando guardano i flussi di emittenti che utilizzano Safari su dispositivi Mac basati su Intel.

  **Soluzione alternativa:** reindirizza gli emittenti su dispositivi Intel Mac per trasmettere tramite Chrome.
+ L'SDK di trasmissione Web richiede che la porta 4443 sia aperta. VPN e firewall possono bloccare la porta 4443 e impedire lo streaming.

  **Soluzione alternativa:** disabilita le VPN e/o configura i firewall per assicurarti che la porta 4443 non sia bloccata. 
+ Il passaggio dalla modalità orizzontale a quella verticale è complicato.

  **Soluzione alternativa:** nessuna.
+ La risoluzione riportata nel manifesto HLS non è corretta. È impostata come la risoluzione inizialmente ricevuta, che di solito è molto inferiore a quella possibile e non riflette alcun upscaling che si verifica durante la durata della connessione WebRTC.

  **Soluzione alternativa:** nessuna.
+ Le istanze client successive create dopo il caricamento della pagina iniziale potrebbero non rispondere alle impostazioni `maxFramerate` che sono diverse dalla prima istanza del client.

  **Soluzione alternativa:** imposta `StreamConfig` sola una volta tramite la funzione `IVSBroadcastClient.create` quando viene creata la prima istanza del client. 
+ Su iOS, l'acquisizione di più sorgenti di dispositivi video non è supportata da WebKit.

  **Soluzione alternativa:** segui [questo problema](https://bugs.webkit.org/show_bug.cgi?id=238492) per monitorare i progressi dello sviluppo.
+ Su iOS, la chiamata a `getUserMedia()` quando si dispone già di una sorgente video interromperà l'utilizzo di qualsiasi altra sorgente video recuperata tramite `getUserMedia()`.

  **Soluzione alternativa:** nessuna.
+ WebRTC sceglie dinamicamente il bitrate e la risoluzione migliori per le risorse disponibili. Il tuo streaming non sarà di alta qualità se l'hardware o la rete non sono in grado di supportarlo. La qualità dello streaming può cambiare durante la trasmissione in quanto sono disponibili più o meno risorse.

  **Soluzione alternativa:** fornire un caricamento di almeno 200 kbps.
+ Se la registrazione automatica su Amazon S3 è abilitata per un canale e si utilizza l'SDK di trasmissione Web, la registrazione con lo stesso prefisso S3 potrebbe non funzionare, poiché l'SDK di trasmissione Web modifica dinamicamente bitrate e qualità.

  **Soluzione alternativa:** nessuna.
+ Quando utilizzi Next.js, è possibile che si verifichi un errore `Uncaught ReferenceError: self is not defined`, a seconda di come viene importato l'SDK.

  **Soluzione alternativa:** [importa dinamicamente la libreria](https://nextjs.org/docs/pages/building-your-application/optimizing/lazy-loading) quando usi Next.js.
+ Potresti non essere in grado di importare il modulo utilizzando un tag di script di tipo `module`; ad esempio,`<script type="module" src="..."\>`.

  **Soluzione alternativa:** la libreria non dispone di una build ES6. Rimuovi il `type="module"` dal tag di script.

## Limiti di Safari
<a name="broadcast-web-safari-limitations"></a>
+ Per negare un prompt di autorizzazione è necessario reimpostare l'autorizzazione nelle impostazioni del sito Web di Safari a livello di sistema operativo.
+ Safari non rileva nativamente tutti i dispositivi con la stessa efficacia di Firefox o Chrome. Ad esempio, OBS Virtual Camera non viene rilevata.

## Limitazioni di Firefox
<a name="broadcast-web-firefox-limitations"></a>
+ Per consentire a Firefox di condividere lo schermo devono essere abilitate le autorizzazioni di sistema. Dopo averle abilitate, perché funzioni correttamente Firefox deve essere riavviato altrimenti, se le autorizzazioni vengono percepite come bloccate, il browser genererà un'eccezione [NotFoundError](https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getDisplayMedia#exceptions).
+ Manca il metodo `getCapabilities`. Ciò significa che gli utenti non possono ottenere la risoluzione o le proporzioni della traccia multimediale. Consulta questo [thread di bugzilla](https://bugzilla.mozilla.org/show_bug.cgi?id=1179084).
+ Mancano diverse proprietà `AudioContext`, ad esempio latenza e numero di canali. Ciò potrebbe rappresentare un problema per gli utenti esperti che desiderano manipolare le tracce audio.
+ I feed della fotocamera da `getUserMedia` su MacOS sono limitati a un rapporto di aspetto 4:3. Consulta il [thread 1 di bugzilla](https://bugzilla.mozilla.org/show_bug.cgi?id=1193640) e [thread 2 di bugzilla](https://bugzilla.mozilla.org/show_bug.cgi?id=1306034).
+ L'acquisizione audio non è supportata con `getDisplayMedia`. Consulta questo [thread di bugzilla](https://bugzilla.mozilla.org/show_bug.cgi?id=1541425).
+ La frequenza di fotogrammi nell'acquisizione dello schermo non è ottimale (circa 15 fps?). Consulta questo [thread di bugzilla](https://bugzilla.mozilla.org/show_bug.cgi?id=1703522).

# SDK di trasmissione IVS: guida per Android \$1 Streaming a bassa latenza
<a name="broadcast-android"></a>

L'SDK di trasmissione a bassa latenza IVS per Android fornisce le interfacce necessarie per trasmettere ad Amazon IVS su Android.

Il pacchetto `com.amazonaws.ivs.broadcast` implementa l'interfaccia descritta in questo documento. Sono supportate le seguenti operazioni: 
+ Impostare (inizializzare) una sessione di trasmissione. 
+ Gestire la trasmissione.
+ Collegare e scollegare dispositivi di input.
+ Gestire una sessione di composizione. 
+ Ricevere eventi. 
+ Ricevere errori. 

**Ultima versione dell'SDK di trasmissione Android:** 1.40.0 ([Note di rilascio](https://docs.aws.amazon.com/ivs/latest/LowLatencyUserGuide/release-notes.html#mar12-26-broadcast-android-ll)) 

**Documentazione di riferimento:** per informazioni sui metodi più importanti disponibili nell'SDK di trasmissione di Amazon IVS per Android, consulta la documentazione di riferimento all'indirizzo [https://aws.github.io/amazon-ivs-'-docs/1.40.0/android/](https://aws.github.io/amazon-ivs-broadcast-docs/1.40.0/android/).

**Codice di esempio:** vedere il repository di esempio Android su GitHub: [https://github.com/aws-samples/amazon-ivs-'-android-sample](https://github.com/aws-samples/amazon-ivs-broadcast-android-sample).

**Requisiti della piattaforma:** Android 9.0\$1

# Guida introduttiva all'SDK di trasmissione IVS per Android \$1 Streaming a bassa latenza
<a name="broadcast-android-getting-started"></a>

Questo documento illustra i passaggi necessari per iniziare a utilizzare l'SDK di trasmissione per lo streaming a bassa latenza di Amazon IVS per Android.

## Installare la libreria
<a name="broadcast-android-install"></a>

Per aggiungere la libreria di trasmissione di Amazon IVS per Android al proprio ambiente di sviluppo Android, aggiungere la libreria al file `build.gradle` come mostrato di seguito (per l'ultima versione dell'SDK di trasmissione di Amazon IVS):

```
repositories {
    mavenCentral()
}
dependencies {
     implementation 'com.amazonaws:ivs-broadcast:1.40.0'
}
```

In alternativa, per installare manualmente l'SDK, scaricare la versione più recente da questo percorso:
+ [https://search.maven.org/artifact/com.amazonaws/ivs-broadcast](https://search.maven.org/artifact/com.amazonaws/ivs-broadcast)

## Utilizzo dell'SDK con i simboli di debug
<a name="broadcast-android-using-debug-symbols-ll"></a>

Pubblichiamo anche una versione dell'SDK di trasmissione per Android che include i simboli di debug. È possibile utilizzare questa versione per migliorare la qualità dei report di debug (tracce dello stack) in Firebase Crashlytics se si verificano arresti anomali nell'SDK di trasmissione IVS, ad esempio `libbroadcastcore.so`. Quando segnali questi arresti anomali al team dell'SDK di IVS, le tracce dello stack di qualità superiore facilitano la risoluzione dei problemi.

Per utilizzare questa versione dell'SDK, inserisci quanto segue nei tuoi file di build di Gradle:

```
implementation "com.amazonaws:ivs-broadcast:$version:unstripped@aar"
```

Utilizza la riga precedente invece di questa:

```
implementation "com.amazonaws:ivs-broadcast:$version@aar"
```

### Caricamento dei simboli in Firebase Crashlytics
<a name="android-debug-symbols-ll-firebase-crashlytics"></a>

Assicurati che i tuoi file di build Gradle siano configurati per Firebase Crashlytics. Segui le istruzioni di Google qui:

[https://firebase.google.com/docs/crashlytics/ndk-reports](https://firebase.google.com/docs/crashlytics/ndk-reports)

Assicurati di includere `com.google.firebase:firebase-crashlytics-ndk` come dipendenza.

Quando crei l'app per il rilascio, il plug-in Firebase Crashlytics dovrebbe caricare i simboli automaticamente. Per caricare i simboli manualmente, esegui uno dei comandi seguenti:

```
gradle uploadCrashlyticsSymbolFileRelease
```

```
./gradlew uploadCrashlyticsSymbolFileRelease
```

Non è un problema se i simboli vengono caricati due volte, automaticamente e manualmente.

### Impedire che .apk Release diventi più grande
<a name="android-debug-symbols-ll-sizing-apk"></a>

Prima di impacchettare il file `.apk` di rilascio, il plug-in Android Gradle tenta automaticamente di rimuovere le informazioni di debug dalle librerie condivise (inclusa la libreria `libbroadcastcore.so` dell'SDK di trasmissione IVS). Tuttavia, a volte ciò non accade. Di conseguenza, il file `.apk` potrebbe diventare più grande e si potrebbe ricevere un messaggio di avviso dal plug-in Android Gradle che indica che non è in grado di rimuovere i simboli di debug e sta impacchettando i file `.so` così come sono. In tal caso, segui questa procedura:
+ Installa un NDK per Android. Va bene qualsiasi versione recente.
+ Aggiungi `ndkVersion <your_installed_ndk_version_number>` al file `build.gradle` dell'applicazione. Fallo anche se l'applicazione non contiene codice nativo.

Per ulteriori informazioni, consulta questo [report sul problema](https://issuetracker.google.com/issues/353554169).

## Creare il listener di eventi
<a name="broadcast-android-create-event-listener"></a>

La configurazione di un listener di eventi consente di ricevere aggiornamenti di stato, notifiche di modifica del dispositivo, errori e informazioni sull'audio della sessione.

```
BroadcastSession.Listener broadcastListener = 
          new BroadcastSession.Listener() {
    @Override
    public void onStateChanged(@NonNull BroadcastSession.State state) {
        Log.d(TAG, "State=" + state);
    }

    @Override
    public void onError(@NonNull BroadcastException exception) {
        Log.e(TAG, "Exception: " + exception);
    }
};
```

## Richiedere autorizzazioni
<a name="broadcast-android-permissions"></a>

L'app deve richiedere l'autorizzazione per accedere alla fotocamera e al microfono dell'utente. (Questo non riguarda solo Amazon IVS, ma qualsiasi applicazione che abbia bisogno di accedere alle fotocamere e ai microfoni.)

Qui, controlliamo se l'utente ha già concesso le autorizzazioni e, in caso contrario, le chiediamo:

```
final String[] requiredPermissions =
         { Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO };

for (String permission : requiredPermissions) {
    if (ContextCompat.checkSelfPermission(this, permission) 
                != PackageManager.PERMISSION_GRANTED) {
        // If any permissions are missing we want to just request them all.
        ActivityCompat.requestPermissions(this, requiredPermissions, 0x100);
        break;
    }
}
```

Qui, otteniamo la risposta dell'utente:

```
@Override
public void onRequestPermissionsResult(int requestCode, 
                                      @NonNull String[] permissions,
                                      @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode,
               permissions, grantResults);
    if (requestCode == 0x100) {
        for (int result : grantResults) {
            if (result == PackageManager.PERMISSION_DENIED) {
                return;
            }
        }
        setupBroadcastSession();
    }
}
```

## Creare la sessione di trasmissione
<a name="broadcast-android-create-session"></a>

L'interfaccia di trasmissione è `com.amazonaws.ivs.broadcast.BroadcastSession`. Inizializzarla con un preset, come mostrato di seguito. Se si verificano errori durante l'inizializzazione (ad esempio un errore nella configurazione di un codec), `BroadcastListener` mostrerà un messaggio di errore e `broadcastSession.isReady` sarà `false`.

**Importante:** tutte le chiamate all'SDK di trasmissione Amazon IVS per Android *devono* essere eseguite sul thread su cui viene istanziato l'SDK. *L'esecuzione di una chiamata da un thread diverso causerà un errore irreversibile dell'SDK e interromperà la trasmissione*.

```
// Create a broadcast-session instance and sign up to receive broadcast
// events and errors.
Context ctx = getApplicationContext();
broadcastSession = new BroadcastSession(ctx,
                       broadcastListener,
                       Presets.Configuration.STANDARD_PORTRAIT,
                       Presets.Devices.FRONT_CAMERA(ctx));
```

Consultare anche [Creare la sessione di trasmissione (versione avanzata)](broadcast-android-use-cases.md#broadcast-android-create-session-advanced).

## Impostare ImagePreviewView per l'anteprima
<a name="broadcast-android-set-imagepreviewview"></a>

Se si desidera visualizzare un'anteprima per un dispositivo fotocamera attivo, aggiungere un'anteprima `ImagePreviewView` per il dispositivo dalla gerarchia delle visualizzazioni.

```
// awaitDeviceChanges will fire on the main thread after all pending devices 
// attachments have been completed
broadcastSession.awaitDeviceChanges(() -> {
    for(Device device: session.listAttachedDevices()) {
        // Find the camera we attached earlier
        if(device.getDescriptor().type == Device.Descriptor.DeviceType.CAMERA) {
            LinearLayout previewHolder = findViewById(R.id.previewHolder);
            ImagePreviewView preview = ((ImageDevice)device).getPreviewView();
            preview.setLayoutParams(new LinearLayout.LayoutParams(
                    LinearLayout.LayoutParams.MATCH_PARENT,
                    LinearLayout.LayoutParams.MATCH_PARENT));
            previewHolder.addView(preview);
        }
    }
});
```

## Avviare una trasmissione
<a name="broadcast-android-start"></a>

Al nome host che si riceve nel campo di risposta `ingestEndpoint` dell'operazione `GetChannel` è necessario anteporre `rtmps://` e posporre `/app`. L'URL completo deve essere in questo formato: `rtmps://{{ ingestEndpoint }}/app`

```
broadcastSession.start(IVS_RTMPS_URL, IVS_STREAMKEY);
```

L'SDK di trasmissione Android supporta solo l'acquisizione RTMPS (non l'acquisizione RTMP non sicura).

## Interrompere una trasmissione
<a name="broadcast-android-stop"></a>

```
broadcastSession.stop();
```

## Rilasciare una sessione di trasmissione
<a name="broadcast-android-release-session"></a>

Quando il lettore non è più in uso *deve essere invocato* il metodo `broadcastSession.release()`, per liberare le risorse utilizzate dalla libreria.

```
@Override
protected void onDestroy() {
    super.onDestroy();
    previewHolder.removeAllViews();
    broadcastSession.release();
}
```

# Casi d'uso avanzati per l'SDK di trasmissione IVS per Android \$1 Streaming a bassa latenza
<a name="broadcast-android-use-cases"></a>

Qui presentiamo alcuni casi d'uso avanzati. Iniziare con la configurazione di base di cui sopra e continuare qui. 

## Creare la configurazione di trasmissione
<a name="broadcast-android-create-configuration"></a>

Qui creiamo una configurazione personalizzata con due slot mixer che ci permettono di associare due fonti video al mixer. Uno (`custom`) è a schermo intero e disposto dietro l'altro (`camera`), che è più piccolo e si trova nell'angolo in basso a destra. Per lo slot `custom` non impostiamo una posizione, una dimensione o una modalità di aspetto. Poiché non impostiamo questi parametri, lo slot utilizzerà le impostazioni del video per le dimensioni e la posizione.

```
BroadcastConfiguration config = BroadcastConfiguration.with($ -> {
    $.audio.setBitrate(128_000);
    $.video.setMaxBitrate(3_500_000);
    $.video.setMinBitrate(500_000);
    $.video.setInitialBitrate(1_500_000);
    $.video.setSize(1280, 720);
    $.mixer.slots = new BroadcastConfiguration.Mixer.Slot[] {
            BroadcastConfiguration.Mixer.Slot.with(slot -> {
                // Do not automatically bind to a source
                slot.setPreferredAudioInput(
                           Device.Descriptor.DeviceType.UNKNOWN);
                // Bind to user image if unbound
                slot.setPreferredVideoInput(
                           Device.Descriptor.DeviceType.USER_IMAGE);
                slot.setName("custom");
                return slot;
            }),
            BroadcastConfiguration.Mixer.Slot.with(slot -> {
                slot.setzIndex(1);
                slot.setAspect(BroadcastConfiguration.AspectMode.FILL);
                slot.setSize(300, 300);
                slot.setPosition($.video.getSize().x - 350,
                        $.video.getSize().y - 350);
                slot.setName("camera");
                return slot;
            })
    };
    return $;
});
```

## Creare la sessione di trasmissione (versione avanzata)
<a name="broadcast-android-create-session-advanced"></a>

Creare una `BroadcastSession` come è stato fatto nell'[esempio di base](broadcast-android-getting-started.md#broadcast-android-create-session), ma fornire qui la propria configurazione personalizzata. Inoltre, inserire `null` per l'array dei dispositivi, perché lo aggiungeremo manualmente.

```
// Create a broadcast-session instance and sign up to receive broadcast
// events and errors.
Context ctx = getApplicationContext();
broadcastSession = new BroadcastSession(ctx,
                       broadcastListener,
                       config, // The configuration we created above
                       null); // We’ll manually attach devices after
```

## Iterare e collegare un dispositivo fotocamera
<a name="broadcast-android-attach-camera"></a>

Qui iteriamo attraverso i vari dispositivi di input rilevati dall'SDK. Su Android 7 (Nougat) questo restituirà solo i dispositivi microfonici predefiniti, perché l'SDK di trasmissione di Amazon IVS non supporta la selezione di dispositivi non predefiniti su questa versione di Android.

Una volta trovato un dispositivo che vogliamo usare, chiamiamo `attachDevice` per collegarlo. Una funzione lambda viene richiamata sul thread principale una volta che il collegamento del dispositivo di input è stato completato. In caso di errore, si riceverà una segnalazione nel listener.

```
for(Device.Descriptor desc: BroadcastSession.listAvailableDevices(getApplicationContext())) {
    if(desc.type == Device.Descriptor.DeviceType.CAMERA &&
            desc.position == Device.Descriptor.Position.FRONT) {
        session.attachDevice(desc, device -> {
            LinearLayout previewHolder = findViewById(R.id.previewHolder);
            ImagePreviewView preview = ((ImageDevice)device).getPreviewView();
            preview.setLayoutParams(new LinearLayout.LayoutParams(
                    LinearLayout.LayoutParams.MATCH_PARENT,
                    LinearLayout.LayoutParams.MATCH_PARENT));
            previewHolder.addView(preview);
            // Bind the camera to the mixer slot we created above.
            session.getMixer().bind(device, "camera");
        });
        break;
    }
}
```

## Scambiare fotocamere
<a name="broadcast-android-swap-cameras"></a>

```
// This assumes you’ve kept a reference called "currentCamera" that points to
// a front facing camera
for(Device device: BroadcastSession.listAvailableDevices()) {
   if(device.type == Device.Descriptor.DeviceType.CAMERA &&
          Device.position != currentCamera.position) {
        // Remove the preview view for the old device.
        // setImagePreviewTextureView is an example function 
        // that handles your view hierarchy.
        setImagePreviewView(null);
        session.exchangeDevices(currentCamera, device, camera -> {
             // Set the preview view for the new device.
             setImagePreviewView(camera.getPreviewView());
             currentCamera = camera;
        });
        break;
   }
}
```

## Creare una superficie di input
<a name="broadcast-android-create-input-surface"></a>

Per inserire dati audio o immagini generati dall'app, utilizzare `createImageInputSource` o `createAudioInputSource`. Entrambi questi metodi creano e collegano dispositivi virtuali che possono essere associati al mixer come qualsiasi altro dispositivo.

La `SurfaceSource` restituita da `createImageInputSource` dispone di un metodo `getInputSurface` che darà un `Surface` che utilizzabile con l'API Camera2, OpenGL o Vulkan, o qualsiasi altra cosa che può scrivere su una superficie.

Il `AudioDevice` restituito da `createAudioInputSource` può ricevere dati PCM lineari generati da AudioRecorder o altri mezzi.

```
SurfaceSource source = session.createImageInputSource();
Surface surface = source.getInputSurface();
session.getMixer().bind(source, “custom”);
```

## Scollegare un dispositivo
<a name="broadcast-android-detach-device"></a>

Se si desidera scollegare e non sostituire un dispositivo, scollegarlo con `Device` o `Device.Descriptor`.

```
session.detachDevice(currentCamera);
```

## Acquisire l'audio dello schermo e del sistema
<a name="broadcast-android-screen-audio-capture"></a>

L'SDK di trasmissione di Amazon IVS per Android include alcuni strumenti che semplificano la cattura dell'audio dello schermo del dispositivo (Android 6 e versioni successive) e del sistema (Android 10 e versioni successive). Se si desidera gestirli manualmente si può creare una fonte di ingresso immagine personalizzata e una fonte di ingresso audio personalizzata.

Per creare una sessione di acquisizione dell'audio dello schermo e del sistema, si avrà bisogno innanzitutto di creare una formula per la richiesta di autorizzazione:

```
public void startScreenCapture() {
    MediaProjectionManager manager =
                         (MediaProjectionManager) getApplicationContext()
                         .getSystemService(Context.MEDIA_PROJECTION_SERVICE);
    if(manager != null) {
        Intent intent = manager.createScreenCaptureIntent();
        startActivityIfNeeded(intent, SCREEN_CAPTURE_REQUEST_ID);
    }
}
```

Per utilizzare questa funzionalità è necessario fornire una classe che estenda `com.amazonaws.ivs.broadcast.SystemCaptureService`. Non è necessario sovrascrivere nessuno dei suoi metodi, ma la classe deve essere specificata per evitare potenziali collisioni tra i servizi.

È necessario anche aggiungere un paio di elementi al proprio manifest Android:

```
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<application ...>
    <service android:name=".ExampleSystemCaptureService"
         android:foregroundServiceType="mediaProjection" 
         android:isolatedProcess="false" />
</application>
...
```

La classe che estende `SystemCaptureService` deve essere denominata nell'elemento `<service>`. Su Android 9 e versioni successive, `foregroundServiceType` deve essere `mediaProjection`.

Una volta ottenuta una risposta alla formula di autorizzazione, si può procedere con la creazione della sessione di acquisizione dell'audio dello schermo e del sistema. Su Android 8 e versioni successive, è necessario fornire una notifica da visualizzare nel Pannello notifiche dell'utente. L'SDK di trasmissione di Amazon IVS per Android fornisce il metodo di convenienza `createServiceNotificationBuilder`. In alternativa, è possibile fornire la propria notifica. 

```
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if(requestCode != SCREEN_CAPTURE_REQUEST_ID
       || Activity.RESULT_OK != resultCode) {
        return;
    }
    Notification notification = null;
    if(Build.VERSION.SDK_INT >= 26) {
        Intent intent = new Intent(getApplicationContext(),
                                   NotificationActivity.class);
        notification = session
                         .createServiceNotificationBuilder("example",
                                            "example channel", intent)
                         .build();
    }
    session.createSystemCaptureSources(data,
                  ExampleSystemCaptureService.class,
                  Notification,
                  devices -> {
        // This step is optional if the mixer slots have been given preferred
        // input device types SCREEN and SYSTEM_AUDIO
        for (Device device : devices) {
            session.getMixer().bind(device, "game");
        }
    });
}
```

## Ottenere impostazioni di trasmissione suggerite
<a name="broadcast-android-recommended-settings"></a>

Per valutare la connessione dell'utente prima di avviare una trasmissione, utilizzare il metodo `recommendedVideoSettings` per eseguire un breve test. Durante l'esecuzione del test, si riceveranno vari suggerimenti ordinati dal più consigliato al meno raccomandato. In questa versione dell'SDK, non è possibile riconfigurare l'attuale `BroadcastSession`, quindi effettuare `release()` e crearne uno nuovo con le impostazioni suggerite. Si continuerà a ricevere `BroadcastSessionTest.Results` fino a che `Result.status` è `SUCCESS` o `ERROR`. È possibile controllare lo stato di avanzamento mediante `Result.progress`.

Amazon IVS supporta un bitrate massimo di 8,5 Mb/s (per i canali il cui `type` è `STANDARD` o `ADVANCED`), quindi il `maximumBitrate` restituito da questo metodo non supera mai 8,5 Mb/s. Per tenere in considerazione le piccole fluttuazioni nelle prestazioni di rete, il `initialBitrate` suggerito restituito da questo metodo è leggermente inferiore al bitrate reale misurato nel test. (Solitamente è sconsigliabile utilizzare il 100% della larghezza di banda disponibile.)

```
void runBroadcastTest() {
    this.test = session.recommendedVideoSettings(RTMPS_ENDPOINT, RTMPS_STREAMKEY,
        result -> {
            if (result.status == BroadcastSessionTest.Status.SUCCESS) {
                this.recommendation = result.recommendations[0];
            }
        });
}
```

## Utilizzo della riconnessione automatica
<a name="broadcast-android-auto-reconnect"></a>

IVS supporta la riconnessione automatica a una trasmissione se la trasmissione si interrompe inaspettatamente senza chiamare l'API `stop`, ad esempio in caso di perdita temporanea della connettività di rete. Per abilitare la riconnessione automatica, chiama `setEnabled(true)` su `BroadcastConfiguration.autoReconnect`.

Quando qualcosa causa l'interruzione imprevista del flusso, l'SDK riprova fino a 5 volte, seguendo una strategia di backoff lineare. Notifica all'applicazione lo stato del nuovo tentativo tramite il metodo `BroadcastSession.Listener.onRetryStateChanged`.

Dietro le quinte, la riconnessione automatica utilizza la funzionalità [stream-takeover](streaming-config.md#streaming-config-stream-takeover) di IVS aggiungendo un numero di priorità, che inizia con 1, alla fine della chiave di flusso fornita. Per tutta la durata dell'istanza `BroadcastSession`, tale numero viene incrementato di 1 ogni volta che viene tentata una riconnessione. Ciò significa che se la connessione del dispositivo viene interrotta 4 volte durante una trasmissione e ogni perdita richiede 1-4 nuovi tentativi, la priorità dell'ultimo flusso in uscita potrebbe essere compresa tra 5 e 17. Per questo motivo, *consigliamo di non utilizzare l'acquisizione del flusso IVS da un altro dispositivo se per lo stesso canale nell'SDK è abilitata la riconnessione automatica*. Non ci sono garanzie sulla priorità utilizzata dall'SDK in quel momento e l'SDK proverà a riconnettersi con una priorità più alta se un altro dispositivo prende il controllo.

## Uso dei microfoni Bluetooth
<a name="broadcast-android-bluetooth-microphones"></a>

Per trasmettere utilizzando dispositivi microfonici Bluetooth, è necessario avviare una connessione Bluetooth SCO:

```
Bluetooth.startBluetoothSco(context);
// Now bluetooth microphones can be used
…
// Must also stop bluetooth SCO
Bluetooth.stopBluetoothSco(context);
```

# Problemi noti e soluzioni alternative per l'SDK di trasmissione IVS per Android \$1 Streaming a bassa latenza
<a name="broadcast-android-issues"></a>

Questo documento elenca i problemi noti che potresti riscontrare durante l'utilizzo dell'SDK di trasmissione dello streaming a bassa latenza di Amazon IVS per Android e suggerisce possibili soluzioni alternative.
+ L'utilizzo di un microfono esterno collegato tramite Bluetooth può generare instabilità. Quando un dispositivo Bluetooth viene collegato o scollegato durante una sessione di trasmissione, l'ingresso del microfono potrebbe smettere di funzionare fino a quando il dispositivo non viene effettivamente scollegato e ricollegato.

  **Soluzione alternativa:** se si prevede di utilizzare un auricolare Bluetooth, collegarlo prima di avviare la trasmissione e lasciarlo connesso per tutta la durata della trasmissione.
+ L'SDK di trasmissione non supporta l'accesso su fotocamere esterne collegate tramite USB.

  **Soluzione alternativa:** non utilizzare fotocamere esterne collegate tramite USB. 
+ L'invio di dati audio più velocemente rispetto al tempo reale (utilizzando una fonte audio personalizzata) determina la perdita di sincronizzazione dell'audio.

  **Soluzione alternativa:** non inviare dati audio a una velocità superiore al tempo reale. 
+ I dispositivi Android 6 e 7 non possono ricevere le richiamate `onDeviceAdded` e `onDeviceRemoved` dell'SDK di trasmissione per i microfoni poiché queste versioni di Android consentono solo l'uso del microfono predefinito di sistema.

  **Soluzione alternativa:** per questi dispositivi, l'SDK di trasmissione utilizza il microfono di default del sistema.
+ Quando una `ImagePreviewView` viene rimossa da un elemento padre (ad esempio, `removeView()` viene chiamato dall'elemento padre), `ImagePreviewView` viene rilasciata immediatamente. `ImagePreviewView` non mostra alcun frame quando viene aggiunta a un'altra vista principale.

  **Soluzione alternativa:** richiedi un'altra anteprima utilizzando `getPreview`.
+ Alcuni codificatori video Android non possono essere configurati con dimensioni video inferiori a 176x176. La configurazione di una dimensione inferiore causa un errore e impedisce lo streaming.

  **Soluzione alternativa:** configura la dimensione del video in modo che non sia inferiore a 176x176.
+ L'attivazione dei B-frame può migliorare la qualità della compressione; tuttavia alcuni codificatori forniscono un controllo del bitrate meno preciso quando i B-frame sono abilitati, il che può causare problemi durante le fluttuazioni della rete.

  **Soluzione alternativa:** considerare la possibilità di disattivare i B-frame se, per il caso d'uso specifico, l'aderenza costante del bitrate è più importante dell'efficienza di compressione.

# SDK di trasmissione IVS: guida per iOS \$1 Streaming a bassa latenza
<a name="broadcast-ios"></a>

L'SDK di trasmissione a bassa latenza IVS per iOS fornisce le interfacce necessarie per trasmettere ad Amazon IVS su iOS.

Il modulo `AmazonIVSBroadcast` implementa l'interfaccia descritta in questo documento. Sono supportate le seguenti operazioni:
+ Impostare (inizializzare) una sessione di trasmissione. 
+ Gestire la trasmissione.
+ Collegare e scollegare dispositivi di input.
+ Gestire una sessione di composizione. 
+ Ricevere eventi. 
+ Ricevere errori. 

**Ultima versione dell'SDK di trasmissione iOS:** 1.40.0 ([Note di rilascio](https://docs.aws.amazon.com/ivs/latest/LowLatencyUserGuide/release-notes.html#mar12-26-broadcast-mobile-ll)) 

**Documentazione di riferimento:** per informazioni sui metodi più importanti disponibili nell'SDK di trasmissione di Amazon IVS per iOS, consulta la documentazione di riferimento all'indirizzo [https://aws.github.io/amazon-ivs-'-docs/1.40.0/ios/](https://aws.github.io/amazon-ivs-broadcast-docs/1.40.0/ios/).

**Codice di esempio:** consultare il repository di esempio iOS su GitHub: [https://github.com/aws-samples/amazon-ivs-'-ios-sample](https://github.com/aws-samples/amazon-ivs-broadcast-ios-sample).

**Requisiti della piattaforma:** iOS 14\$1

## Come iOS sceglie la risoluzione della fotocamera e la frequenza dei fotogrammi
<a name="ios-publish-subscribe-resolution-framerate"></a>

La fotocamera gestita dall'SDK di trasmissione ottimizza la risoluzione e la frequenza dei fotogrammi (fotogrammi al secondo o FPS) per ridurre al minimo la produzione di calore e il consumo di energia. Questa sezione spiega come vengono selezionati la risoluzione e la frequenza dei fotogrammi per ottimizzare le applicazioni host per i rispettivi casi d'uso.

Quando si collega una `IVSCamera` a una `IVSBroadcastSession`, la fotocamera è ottimizzata per una frequenza dei fotogrammi di `IVSVideoConfiguration.targetFramerate` e una risoluzione di `IVSVideoConfiguration.size`. Questi valori vengono forniti alla `IVSBroadcastSession` all'inizializzazione. 

# Guida introduttiva all'SDK di trasmissione IVS per iOS \$1 Streaming a bassa latenza
<a name="broadcast-ios-getting-started"></a>

Questo documento illustra i passaggi necessari per iniziare a utilizzare l'SDK di trasmissione per lo streaming a bassa latenza di Amazon IVS per iOS.

## Installare la libreria
<a name="broadcast-ios-install"></a>

Si consiglia di integrare l'SDK di trasmissione tramite Swift Package Manager. (in alternativa, esiste la possibilità di aggiungere il framework al proprio progetto manualmente).

### Consigliato: Integrare l'SDK di trasmissione (Swift Package Manager)
<a name="broadcast-ios-install-swift"></a>

1. Scaricare il file Package.swift da [https://broadcast.live-video.net/1.40.0/Package.swift](https://broadcast.live-video.net/1.40.0/Package.swift).

1. Nel tuo progetto, crea una nuova directory denominata AmazonIVSBroadcast e aggiungila al controllo delle versioni.

1. Inserire il file Package.swift file nella nuova directory.

1. In Xcode, vai su **File > Aggiungi dipendenze del pacchetto** e seleziona **Aggiungi locale…**

1. Passare e selezionare la directory AmazonIVSBroadcast creata e selezionare **Aggiungi pacchetto**.

1. Quando viene richiesto di **scegliere i prodotti del pacchetto per AmazonIVSBroadcast**, selezionare **AmazonIVSBroadcast** come **prodotto del pacchetto** impostando la destinazione dell'applicazione nella sezione **Aggiungi alla destinazione**.

1. Seleziona **Aggiungi pacchetto**.

### Approccio alternativo: installare manualmente il framework
<a name="broadcast-ios-install-manual"></a>

1. Scarica l'ultima versione da [https://'.live-video.net/1.40.0/AmazonIVSBroadcast.xcframework.zip](https://broadcast.live-video.net/1.40.0/AmazonIVSBroadcast.xcframework.zip).

1. Estrarre i contenuti dell'archivio. `AmazonIVSBroadcast.xcframework` contiene l'SDK sia per il dispositivo sia per il simulatore.

1. Incorporare `AmazonIVSBroadcast.xcframework` trascinandolo nella sezione **Framework, librerie e contenuto incorporato** della scheda **Generali** per il target dell'applicazione.  
![\[La sezione Framework, librerie e contenuto incorporato della scheda Generali per il target dell'applicazione.\]](http://docs.aws.amazon.com/it_it/ivs/latest/LowLatencyUserGuide/images/iOS_Broadcast_SDK_Guide_xcframework.png)

## Implementare IVSBroadcastSession.Delegate
<a name="broadcast-ios-implement-ivsbroadcastsessiondelegate"></a>

Implementare `IVSBroadcastSession.Delegate`, che consente di ricevere aggiornamenti sullo stato e notifiche relative alle modifiche al dispositivo:

```
extension ViewController : IVSBroadcastSession.Delegate {
   func broadcastSession(_ session: IVSBroadcastSession,
                         didChange state: IVSBroadcastSession.State) {
      print("IVSBroadcastSession did change state \(state)")
   }

   func broadcastSession(_ session: IVSBroadcastSession,
                         didEmitError error: Error) {
      print("IVSBroadcastSession did emit error \(error)")
   }
}
```

## Richiedere autorizzazioni
<a name="broadcast-ios-permissions"></a>

L'app deve richiedere l'autorizzazione per accedere alla fotocamera e al microfono dell'utente. (Questo non riguarda solo Amazon IVS, ma qualsiasi applicazione che abbia bisogno di accedere alle fotocamere e ai microfoni.)

Qui, controlliamo se l'utente ha già concesso le autorizzazioni e, in caso contrario, ne facciamo richiesta:

```
switch AVCaptureDevice.authorizationStatus(for: .video) {
case .authorized: // permission already granted.
case .notDetermined:
   AVCaptureDevice.requestAccess(for: .video) { granted in
       // permission granted based on granted bool.
   }
case .denied, .restricted: // permission denied.
@unknown default: // permissions unknown.
}
```

È necessario eseguire questa operazione per entrambe le tipologie di contenuti multimediali `.video` e `.audio`, se si desidera accedere rispettivamente a fotocamere e microfoni.

Inoltre, è necessario aggiungere voci per `NSCameraUsageDescription` e `NSMicrophoneUsageDescription` a `Info.plist`. In caso contrario, quando si tenta di richiedere le autorizzazioni l'app potrebbe subire un arresto anomalo.

## Disabilitare il timer di inattività dell'applicazione
<a name="broadcast-ios-disable-idle-timer"></a>

Questo passaggio è facoltativo, ma è consigliato. Impedisce al dispositivo di andare in sospensione durante l'utilizzo dell'SDK di trasmissione, che causerebbe l'interruzione della trasmissione.

```
override func viewDidAppear(_ animated: Bool) {
   super.viewDidAppear(animated)
   UIApplication.shared.isIdleTimerDisabled = true
}
override func viewDidDisappear(_ animated: Bool) {
   super.viewDidDisappear(animated)
   UIApplication.shared.isIdleTimerDisabled = false
}
```

## (Facoltativo) Impostare AVAudioSession
<a name="broadcast-ios-setup-avaudiosession"></a>

Per impostazione predefinita, l'SDK di trasmissione configurerà l' dell'applicazione `AVAudioSession`. Se si vuole gestirla in modo autonomo, impostare `IVSBroadcastSession.applicationAudioSessionStrategy` su `noAction`. Senza controllo del `AVAudioSession`, l'SDK di trasmissione non è in grado di gestire i microfoni internamente. Per utilizzare i microfoni con l'opzione `noAction`, esiste la possibilità di creare un `IVSCustomAudioSource` e fornire i propri campioni tramite un `AVCaptureSession`, `AVAudioEngine` o un altro strumento che fornisce campioni audio PCM.

Se si configura manualmente la `AVAudioSession`, come minimo è necessario impostare la categoria come `.record` o `.playbackAndRecord` e impostarla su `active`. Se si desidera registrare audio da dispositivi Bluetooth, è necessario specificare anche l'opzione `.allowBluetooth`:

```
do {
   try AVAudioSession.sharedInstance().setCategory(.record, options: .allowBluetooth)
   try AVAudioSession.sharedInstance().setActive(true)
} catch {
   print("Error configuring AVAudioSession")
}
```

Consigliamo di lasciare che l'SDK gestisca questo aspetto. In caso contrario, se si desidera scegliere tra vari dispositivi audio, sarà necessario gestire manualmente le porte.

## Creare la sessione di trasmissione
<a name="broadcast-ios-create-session"></a>

L'interfaccia di trasmissione è `IVSBroadcastSession`. Inizializzare come illustrato di seguito:

```
let broadcastSession = try IVSBroadcastSession(
   configuration: IVSPresets.configurations().standardLandscape(),
   descriptors: IVSPresets.devices().frontCamera(),
   delegate: self)
```

Consultare anche [Creare la sessione di trasmissione (versione avanzata)](broadcast-ios-use-cases.md#broadcast-ios-create-session-advanced)

## Impostare IVSImagePreviewView per l'anteprima
<a name="broadcast-ios-set-imagepreviewview"></a>

Se si desidera visualizzare un'anteprima per un dispositivo fotocamera attivo, aggiungere l'anteprima `IVSImagePreviewView` per il dispositivo dalla gerarchia delle visualizzazioni:

```
// If the session was just created, execute the following 
// code in the callback of IVSBroadcastSession.awaitDeviceChanges 
// to ensure all devices have been attached.
if let devicePreview = try broadcastSession.listAttachedDevices()
   .compactMap({ $0 as? IVSImageDevice })
   .first?
   .previewView()
{
   previewView.addSubview(devicePreview)
}
```

## Avviare una trasmissione
<a name="broadcast-ios-start"></a>

Al nome host che si riceve nel campo di risposta `ingestEndpoint` dell'operazione `GetChannel` è necessario anteporre `rtmps://` e posporre `/app`. L'URL completo deve essere in questo formato: `rtmps://{{ ingestEndpoint }}/app`

```
try broadcastSession.start(with: IVS_RTMPS_URL, streamKey: IVS_STREAMKEY)
```

 L'SDK di trasmissione iOS supporta solo l'acquisizione RTMPS (non l'acquisizione RTMP non sicura). 

## Interrompere una trasmissione
<a name="broadcast-ios-stop"></a>

```
broadcastSession.stop()
```

## Gestire gli eventi del ciclo di vita
<a name="broadcast-ios-lifecycle-events"></a>

### Interruzioni dell'audio
<a name="broadcast-ios-audio-interruptions"></a>

Ci sono varie situazioni in cui l'SDK di trasmissione non avrà accesso esclusivo all'hardware di ingresso audio. Di seguito si trovano alcuni esempi di situazioni da gestire:
+ L'utente riceve una telefonata o una chiamata FaceTime
+ L'utente attiva Siri

Con Apple si può rispondere facilmente a questi eventi iscrivendosi a `AVAudioSession.interruptionNotification`:

```
NotificationCenter.default.addObserver(
   self,
   selector: #selector(audioSessionInterrupted(_:)),
   name: AVAudioSession.interruptionNotification,
   object: nil)
```

Quindi, è possibile gestire l'evento con una delle seguenti opzioni:

```
// This assumes you have a variable `isRunning` which tracks if the broadcast is currently live, and another variable `wasRunningBeforeInterruption` which tracks whether the broadcast was active before this interruption to determine if it should resume after the interruption has ended.

@objc
private func audioSessionInterrupted(_ notification: Notification) {
   guard let userInfo = notification.userInfo,
         let typeValue = userInfo[AVAudioSessionInterruptionTypeKey] as? UInt,
         let type = AVAudioSession.InterruptionType(rawValue: typeValue)
   else {
      return
   }
   switch type {
   case .began:
      wasRunningBeforeInterruption = isRunning
      if isRunning {
         broadcastSession.stop()
      }
   case .ended:
      defer {
         wasRunningBeforeInterruption = false
      }
      guard let optionsValue = userInfo[AVAudioSessionInterruptionOptionKey] as? UInt else { return }
      let options = AVAudioSession.InterruptionOptions(rawValue: optionsValue)
      if options.contains(.shouldResume) && wasRunningBeforeInterruption {
         try broadcastSession.start(
            with: IVS_RTMPS_URL,
            streamKey: IVS_STREAMKEY)
      }
   @unknown default: break
   }
}
```

### App mandata in background
<a name="broadcast-ios-app-to-background"></a>

Su iOS le applicazioni standard non sono autorizzate a utilizzare fotocamere in background. Esistono anche restrizioni sulla codifica video in background: poiché i codificatori hardware sono limitati, solo le applicazioni in primo piano hanno accesso. Per questo motivo, l'SDK di trasmissione termina automaticamente la sua sessione e imposta la sua proprietà `isReady` su `false`. Quando l'applicazione sta per entrare di nuovo in primo piano, l'SDK di trasmissione ricollega tutti i dispositivi alle loro voci `IVSMixerSlotConfiguration` originali.

L'SDK di trasmissione lo fa rispondendo a `UIApplication.didEnterBackgroundNotification` e `UIApplication.willEnterForegroundNotification`.

Se si forniscono fonti di immagine personalizzate, è necessario prepararsi a gestire queste notifiche. Potrebbe essere necessario prendere ulteriori contromisure per abbatterle prima che il flusso venga terminato.

Consultare [Usa video in background](broadcast-ios-use-cases.md#broadcast-ios-background-video) per una soluzione alternativa che consenta lo streaming mentre l'applicazione è in background.

### Media Services (Servizi multimediali) persi
<a name="broadcast-ios-media-services-lost"></a>

In casi molto rari, sui dispositivi iOS si bloccherà l'intero sottosistema multimediale. In questa situazione, non possiamo più trasmettere. Spetterà all'applicazione rispondere in modo appropriato a queste notifiche. Come minimo, consigliamo di iscriversi a queste notifiche:
+ [mediaServicesWereLostNotification](https://developer.apple.com/documentation/avfaudio/avaudiosession/1616457-mediaserviceswerelostnotificatio) - Rispondere interrompendo la trasmissione e deallocando completamente la propria `IVSBroadcastSession`. Tutti i componenti interni utilizzati dalla sessione di trasmissione verranno invalidati.
+ [mediaServicesWereResetNotification](https://developer.apple.com/documentation/avfaudio/avaudiosession/1616540-mediaserviceswereresetnotificati) - Rispondere informando gli utenti che possono trasmettere di nuovo. A seconda dei casi d'uso, si potrebbe avere la possibilità di riavviare automaticamente la trasmissione.

# Casi d'uso avanzati per l'SDK di trasmissione IVS per iOS \$1 Streaming a bassa latenza
<a name="broadcast-ios-use-cases"></a>

Qui presentiamo alcuni casi d'uso avanzati. Iniziare con la configurazione di base di cui sopra e continuare qui.

## Creare la configurazione di trasmissione
<a name="broadcast-ios-create-configuration"></a>

Qui creiamo una configurazione personalizzata con due slot mixer che ci permettono di associare due fonti video al mixer. Uno (`custom`) è a schermo intero e disposto dietro l'altro (`camera`), che è più piccolo e si trova nell'angolo in basso a destra. Per lo slot `custom` non impostiamo una posizione, una dimensione o una modalità di aspetto. Poiché non impostiamo questi parametri, lo slot utilizza le impostazioni video per ciò che riguarda dimensioni e posizione.

```
let config = IVSBroadcastConfiguration()
try config.audio.setBitrate(128_000)
try config.video.setMaxBitrate(3_500_000)
try config.video.setMinBitrate(500_000)
try config.video.setInitialBitrate(1_500_000)
try config.video.setSize(CGSize(width: 1280, height: 720))
config.video.defaultAspectMode = .fit
config.mixer.slots = [
    try {
        let slot = IVSMixerSlotConfiguration()
        // Do not automatically bind to a source
        slot.preferredAudioInput = .unknown
        // Bind to user image if unbound
        slot.preferredVideoInput = .userImage
        try slot.setName("custom")
        return slot
    }(),
    try {
        let slot = IVSMixerSlotConfiguration()
        slot.zIndex = 1
        slot.aspect = .fill
        slot.size = CGSize(width: 300, height: 300)
        slot.position = CGPoint(x: config.video.size.width - 400, y: config.video.size.height - 400)
        try slot.setName("camera")
        return slot
    }()
]
```

## Creare la sessione di trasmissione (versione avanzata)
<a name="broadcast-ios-create-session-advanced"></a>

Creare una `IVSBroadcastSession` come nell'[esempio di base](broadcast-ios-getting-started.md#broadcast-ios-create-session), ma fornire qui la propria configurazione personalizzata. Inoltre, inserire `nil` per l'array dei dispositivi, perché lo aggiungeremo manualmente.

```
let broadcastSession = try IVSBroadcastSession(
   configuration: config, // The configuration we created above
   descriptors: nil, // We’ll manually attach devices after
   delegate: self)
```

## Iterare e collegare un dispositivo fotocamera
<a name="broadcast-ios-attach-camera"></a>

Qui iteriamo attraverso i vari dispositivi di input rilevati dall'SDK. L'SDK restituirà solo i dispositivi integrati in iOS. Anche se i dispositivi audio Bluetooth sono collegati, verranno visualizzati come un dispositivo incorporato. Per ulteriori informazioni, consulta [Problemi noti e soluzioni alternative per l'SDK di trasmissione IVS per iOS \$1 Streaming a bassa latenza](broadcast-ios-issues.md).

Una volta che troviamo un dispositivo che desideriamo utilizzare, per collegarlo utilizziamo una chiamata `attachDevice`:

```
let frontCamera = IVSBroadcastSession.listAvailableDevices()
    .filter { $0.type == .camera && $0.position == .front }
    .first
if let camera = frontCamera {
    broadcastSession.attach(camera, toSlotWithName: "camera") { device, error in
        // check error
    }
}
```

## Scambiare fotocamere
<a name="broadcast-ios-swap-cameras"></a>

```
// This assumes you’ve kept a reference called `currentCamera` that points to the current camera.
let wants: IVSDevicePosition = (currentCamera.descriptor().position == .front) ? .back : .front
// Remove the current preview view since the device will be changing.
previewView.subviews.forEach { $0.removeFromSuperview() }
let foundCamera = IVSBroadcastSession
        .listAvailableDevices()
        .first { $0.type == .camera && $0.position == wants }
guard let newCamera = foundCamera else { return }
broadcastSession.exchangeOldDevice(currentCamera, withNewDevice: newCamera) { newDevice, _ in
    currentCamera = newDevice
    if let camera = newDevice as? IVSImageDevice {
        do {
            previewView.addSubview(try finalCamera.previewView())
        } catch {
            print("Error creating preview view \(error)")
        }
    }
}
```

## Creare una fonte di ingresso personalizzata
<a name="broadcast-ios-create-input-source"></a>

Per inserire dati audio o immagini generati dall'app, utilizza `createImageSource` o `createAudioSource`. Entrambi questi metodi creano dispositivi virtuali (`IVSCustomImageSource` e `IVSCustomAudioSource`) che possono essere associati al mixer come qualsiasi altro dispositivo.

I dispositivi restituiti da entrambi questi metodi accettano un `CMSampleBuffer`attraverso la sua funzione `onSampleBuffer`:
+ Per le fonti video, il formato pixel deve essere `kCVPixelFormatType_32BGRA`, `420YpCbCr8BiPlanarFullRange` oppure `420YpCbCr8BiPlanarVideoRange`.
+ Per le fonti audio, il buffer deve contenere dati PCM lineari.

Non è possibile utilizzare una `AVCaptureSession` con l'input della fotocamera per il feed di una fonte immagine personalizzata, utilizzando al contempo un dispositivo fotocamera fornito dall'SDK di trasmissione. Se si desidera utilizzare più fotocamere contemporaneamente, utilizzare `AVCaptureMultiCamSession` e fornire due fonti di immagini personalizzate.

Le fonti di immagini personalizzate devono essere utilizzate principalmente con contenuti statici come immagini o con contenuti video:

```
let customImageSource = broadcastSession.createImageSource(withName: "video")
try broadcastSession.attach(customImageSource, toSlotWithName: "custom")
```

## Controllare la connettività di rete
<a name="broadcast-ios-network-connection"></a>

Capita spesso che durante gli spostamenti i dispositivi mobili perdano temporaneamente e riacquistino la connettività di rete. Per questo motivo, è importante monitorare la connettività di rete dell'app e rispondere in modo appropriato quando si verificano cambiamenti. 

Quando la connessione della trasmissione viene persa, lo stato dell'SDK di trasmissione cambierà in `error` e poi in `disconnected`. Si riceverà una notifica riguardo a queste modifiche tramite `IVSBroadcastSessionDelegate`. Quando si ricevono queste modifiche dello stato:

1. Monitorare lo stato di connettività dell'app di trasmissione ed effettuare una chiamata `start` con l'endpoint e la chiave di flusso, una volta che la connessione è stata ripristinata.

1. **Importante:** monitorare il callback del delegato dello stato e assicurarsi che lo stato cambi in `connected` dopo avere chiamato nuovamente `start`.

## Scollegare un dispositivo
<a name="broadcast-ios-detach-device"></a>

Se si desidera distaccare e non sostituire un dispositivo, distaccarlo con `IVSDevice` o `IVSDeviceDescriptor`:

```
broadcastSession.detachDevice(currentCamera)
```

## Integrazione di ReplayKit
<a name="broadcast-ios-replaykit"></a>

Per riprodurre in streaming lo schermo del dispositivo e l'audio di sistema su iOS, è necessario effettuare un'integrazione con [ReplayKit](https://developer.apple.com/documentation/replaykit?language=objc). L'SDK di trasmissione di Amazon IVS semplifica l'integrazione di ReplayKit utilizzando `IVSReplayKitBroadcastSession`. Nella propria sottoclasse `RPBroadcastSampleHandler`, creare un'istanza di `IVSReplayKitBroadcastSession`, quindi:
+ Avviare la sessione in `broadcastStarted`
+ Interrompere la sessione in `broadcastFinished`

L'oggetto sessione avrà tre fonti personalizzate per le immagini dello schermo, l'audio dell'app e l'audio del microfono. Passare i `CMSampleBuffers` forniti nel `processSampleBuffer` a tali fonti personalizzate.

Per gestire l'orientamento del dispositivo, è necessario estrarre i metadati specifici di Replaykit dal buffer del sample. Eseguire il seguente codice:

```
let imageSource = session.systemImageSource;
if let orientationAttachment = CMGetAttachment(sampleBuffer, key: RPVideoSampleOrientationKey as CFString, attachmentModeOut: nil) as? NSNumber,
    let orientation = CGImagePropertyOrientation(rawValue: orientationAttachment.uint32Value) {
    switch orientation {
    case .up, .upMirrored:
        imageSource.setHandsetRotation(0)
    case .down, .downMirrored:
        imageSource.setHandsetRotation(Float.pi)
    case .right, .rightMirrored:
        imageSource.setHandsetRotation(-(Float.pi / 2))
    case .left, .leftMirrored:
        imageSource.setHandsetRotation((Float.pi / 2))
    }
}
```

Si può integrare ReplayKit utilizzando la `IVSBroadcastSession` al posto della `IVSReplayKitBroadcastSession`. Tuttavia, la variante specifica di Replaykit ha diverse modifiche per ridurre l'ingombro della memoria interna, così da non superare il tetto di memoria stabilito da Apple per le estensioni di trasmissione.

## Ottenere impostazioni di trasmissione suggerite
<a name="broadcast-ios-recommended-settings"></a>

Per valutare la connessione utente prima di avviare una trasmissione, utilizzare `IVSBroadcastSession.recommendedVideoSettings` per eseguire un breve test. Durante l'esecuzione del test, riceverai vari suggerimenti che sono ordinati dal più consigliato al meno raccomandato. In questa versione dell'SDK, non è possibile riconfigurare l'attuale `IVSBroadcastSession`, pertanto è necessario deallocarla e quindi crearne una nuova con le impostazioni consigliate. Si continuerà a ricevere `IVSBroadcastSessionTestResults` fino a che `result.status` è `Success` o `Error`. È possibile controllare lo stato di avanzamento mediante `result.progress`.

Amazon IVS supporta un bitrate massimo di 8,5 Mb/s (per i canali il cui `type` è `STANDARD` o `ADVANCED`), quindi il `maximumBitrate` restituito da questo metodo non supera mai 8,5 Mb/s. Per tenere in considerazione le piccole fluttuazioni nelle prestazioni di rete, il `initialBitrate` suggerito restituito da questo metodo è leggermente inferiore al bitrate reale misurato nel test. (Solitamente è sconsigliabile utilizzare il 100% della larghezza di banda disponibile.)

```
func runBroadcastTest() {
    self.test = session.recommendedVideoSettings(with: IVS_RTMPS_URL, streamKey: IVS_STREAMKEY) { [weak self] result in
        if result.status == .success {
            self?.recommendation = result.recommendations[0];
        }
    }
}
```

## Utilizzo della riconnessione automatica
<a name="broadcast-ios-auto-reconnect"></a>

IVS supporta la riconnessione automatica a una trasmissione se la trasmissione si interrompe inaspettatamente senza chiamare l'API `stop`, ad esempio in caso di perdita temporanea della connettività di rete. Per abilitare la riconnessione automatica, imposta la proprietà `enabled` su `IVSBroadcastConfiguration.autoReconnect` su `true`.

Quando qualcosa causa l'interruzione imprevista del flusso, l'SDK riprova fino a 5 volte, seguendo una strategia di backoff lineare. Notifica all'applicazione lo stato del nuovo tentativo tramite la funzione `IVSBroadcastSessionDelegate.didChangeRetryState`.

Dietro le quinte, la riconnessione automatica utilizza la funzionalità [stream-takeover](streaming-config.md#streaming-config-stream-takeover) di IVS aggiungendo un numero di priorità, che inizia con 1, alla fine della chiave di flusso fornita. Per tutta la durata dell'istanza `IVSBroadcastSession`, tale numero viene incrementato di 1 ogni volta che viene tentata una riconnessione. Ciò significa che se la connessione del dispositivo viene interrotta 4 volte durante una trasmissione e ogni perdita richiede 1-4 nuovi tentativi, la priorità dell'ultimo flusso in uscita potrebbe essere compresa tra 5 e 17. Per questo motivo, *consigliamo di non utilizzare l'acquisizione del flusso IVS da un altro dispositivo se per lo stesso canale nell'SDK è abilitata la riconnessione automatica*. Non ci sono garanzie sulla priorità utilizzata dall'SDK in quel momento e l'SDK proverà a riconnettersi con una priorità più alta se un altro dispositivo prende il controllo.

## Usare video in background
<a name="broadcast-ios-background-video"></a>

È possibile continuare una trasmissione non Relaykit, anche con l'applicazione in background.

Per risparmiare energia e mantenere reattive le applicazioni in primo piano, iOS offre l'accesso alla GPU a una sola applicazione alla volta. L'SDK di trasmissione di Amazon IVS utilizza la GPU in più fasi della pipeline video, inclusa la composizione di più sorgenti di ingresso, il ridimensionamento dell'immagine e la codifica dell'immagine. Mentre l'applicazione di trasmissione è in background, non vi è alcuna garanzia che l'SDK possa eseguire queste operazioni.

Per risolvere questo problema, utilizzare il metodo `createAppBackgroundImageSource`. Consente all'SDK di continuare a trasmettere video e audio in background. Restituisce un `IVSBackgroundImageSource`, che è un `IVSCustomImageSource` normale con una funzione `finish` aggiuntiva. Ogni `CMSampleBuffer` fornito alla sorgente di immagini in background è codificato alla frequenza di fotogrammi fornita dalla `IVSVideoConfiguration` originale. I timestamp sul `CMSampleBuffer` vengono ignorati.

L'SDK quindi dimensiona e codifica le immagini e le memorizza nella cache, eseguendo automaticamente il loop di quel feed quando l'applicazione entra in background. Quando l'applicazione torna in primo piano, i dispositivi immagine collegati diventano nuovamente attivi e il flusso pre-codificato interrompe il ciclo.

Per annullare questo processo, utilizzare `removeImageSourceOnAppBackgrounded`. Non è necessario chiamarlo a meno che non si desideri ripristinare esplicitamente il comportamento in background dell'SDK; in caso contrario, viene ripulito automaticamente alla deallocazione della `IVSBroadcastSession`.

**Note:** *si consiglia vivamente di chiamare questo metodo come parte della configurazione della sessione di trasmissione, prima che la sessione diventi attiva.* Il metodo è costoso (codifica video), quindi le prestazioni di una trasmissione in diretta mentre questo metodo è in esecuzione potrebbero risultare ridotte.

### Esempio: generazione di un'immagine statica per il video in background
<a name="background-video-example-static-image"></a>

La fornitura di una singola immagine alla fonte in background genera un GOP completo di quell'immagine statica.

Di seguito è riportato un esempio che utilizza CIImage:

```
// Create the background image source
guard let source = session.createAppBackgroundImageSource(withAttemptTrim: true, onComplete: { error in
    print("Background Video Generation Done - Error: \(error.debugDescription)")
}) else {
    return
}

// Create a CIImage of the color red.
let ciImage = CIImage(color: .red)

// Convert the CIImage to a CVPixelBuffer
let attrs = [
    kCVPixelBufferCGImageCompatibilityKey: kCFBooleanTrue,
    kCVPixelBufferCGBitmapContextCompatibilityKey: kCFBooleanTrue,
    kCVPixelBufferMetalCompatibilityKey: kCFBooleanTrue,
] as CFDictionary

var pixelBuffer: CVPixelBuffer!
CVPixelBufferCreate(kCFAllocatorDefault,
                    videoConfig.width,
                    videoConfig.height,
                    kCVPixelFormatType_420YpCbCr8BiPlanarFullRange,
                    attrs,
                    &pixelBuffer)

let context = CIContext()
context.render(ciImage, to: pixelBuffer)

// Submit to CVPixelBuffer and finish the source
source.add(pixelBuffer)
source.finish()
```

In alternativa, invece di creare un'immagine CIImage a tinta unita, è possibile utilizzare immagini in bundle. L'unico codice mostrato qui è come convertire un UIImage in un CIImage da utilizzare con l'esempio precedente:

```
// Load the pre-bundled image and get it’s CGImage
guard let cgImage = UIImage(named: "image")?.cgImage else {
    return
}

// Create a CIImage from the CGImage
let ciImage = CIImage(cgImage: cgImage)
```

### Esempio: video con AVAssetImageGenerator
<a name="background-video-example-avassetimagegenerator"></a>

Si può utilizzare un `AVAssetImageGenerator` per generare `CMSampleBuffers` da un `AVAsset` (anche se non è un `AVAsset` del flusso HLS):

```
// Create the background image source
guard let source = session.createAppBackgroundImageSource(withAttemptTrim: true, onComplete: { error in
    print("Background Video Generation Done - Error: \(error.debugDescription)")
}) else {
    return
}

// Find the URL for the pre-bundled MP4 file
guard let url = Bundle.main.url(forResource: "sample-clip", withExtension: "mp4") else {
    return
}
// Create an image generator from an asset created from the URL.
let generator = AVAssetImageGenerator(asset: AVAsset(url: url))
// It is important to specify a very small time tolerance.
generator.requestedTimeToleranceAfter = .zero
generator.requestedTimeToleranceBefore = .zero

// At 30 fps, this will generate 4 seconds worth of samples.
let times: [NSValue] = (0...120).map { NSValue(time: CMTime(value: $0, timescale: CMTimeScale(config.video.targetFramerate))) }
var completed = 0

let context = CIContext(options: [.workingColorSpace: NSNull()])

// Create a pixel buffer pool to efficiently feed the source
let attrs = [
    kCVPixelBufferPixelFormatTypeKey: kCVPixelFormatType_420YpCbCr8BiPlanarFullRange,
    kCVPixelBufferCGImageCompatibilityKey: kCFBooleanTrue,
    kCVPixelBufferCGBitmapContextCompatibilityKey: kCFBooleanTrue,
    kCVPixelBufferMetalCompatibilityKey: kCFBooleanTrue,
    kCVPixelBufferWidthKey: videoConfig.width,
    kCVPixelBufferHeightKey: videoConfig.height,
] as CFDictionary
var pool: CVPixelBufferPool!
CVPixelBufferPoolCreate(kCFAllocatorDefault, nil, attrs, &pool)

generator.generateCGImagesAsynchronously(forTimes: times) { requestTime, image, actualTime, result, error in
    if let image = image {
        // convert to CIImage then CVpixelBuffer
        let ciImage = CIImage(cgImage: image)
        var pixelBuffer: CVPixelBuffer!
        CVPixelBufferPoolCreatePixelBuffer(kCFAllocatorDefault, pool, &pixelBuffer)
        context.render(ciImage, to: pixelBuffer)
        source.add(pixelBuffer)
    }
    completed += 1
    if completed == times.count {
        // Mark the source finished when all images have been processed
        source.finish()
    }
}
```

È possibile generare `CVPixelBuffers` tramite un `AVPlayer` e `AVPlayerItemVideoOutput`. Tuttavia, ciò richiede l'utilizzo di un `CADisplayLink` e l'esecuzione è più vicina al tempo reale, mentre `AVAssetImageGenerator` può elaborare i fotogrammi molto più velocemente.

### Limitazioni
<a name="background-video-limitations"></a>

L'applicazione ha bisogno di [diritti audio in background](https://developer.apple.com/documentation/xcode/configuring-background-execution-modes) per evitare che venga sospesa dopo essere passata in background.

`createAppBackgroundImageSource` può essere chiamato solo mentre l'applicazione è in primo piano, poiché per il suo completamento è necessario accedere alla GPU.

`createAppBackgroundImageSource` codifica sempre in un GOP completo. Ad esempio, se si dispone di un intervallo di fotogrammi chiave di 2 secondi (impostazione di default) e si esegue a 30 fps, codifica un multiplo di 60 fotogrammi.
+ Se vengono forniti meno di 60 fotogrammi, l'ultimo fotogramma viene ripetuto fino al raggiungimento di 60 fotogrammi, indipendentemente dal valore dell'opzione di taglio.
+ Se vengono forniti più di 60 fotogrammi e l'opzione di rifinitura è `true`, gli ultimi N frame vengono eliminati, dove N è il resto del numero totale di fotogrammi inviati diviso per 60.
+ Se vengono forniti più di 60 fotogrammi e l'opzione di rifinitura è `false`, l'ultimo fotogramma viene ripetuto fino al raggiungimento del multiplo successivo di 60 fotogrammi.

# Problemi noti e soluzioni alternative per l'SDK di trasmissione IVS per iOS \$1 Streaming a bassa latenza
<a name="broadcast-ios-issues"></a>

Questo documento elenca i problemi noti che potresti riscontrare durante l'utilizzo dell'SDK di trasmissione dello streaming a bassa latenza di Amazon IVS per iOS e suggerisce possibili soluzioni alternative.
+ Un bug in ReplayKit causa una rapida crescita della memoria quando si collega un auricolare con cavo durante una trasmissione.

  **Soluzione alternativa:** avviare lo streaming con l'auricolare con cavo già collegato, utilizzare un auricolare Bluetooth o non utilizzare un microfono esterno.
+ Se in un momento qualsiasi durante una trasmissione ReplayKit si abilita il microfono e si interrompe la sessione audio (ad esempio, per una telefonata o attivando Siri), l'audio del sistema smetterà di funzionare. Questo è un bug di ReplayKit e stiamo collaborando con Apple per risolverlo.

  **Soluzione alternativa:** in caso di interruzione dell'audio, interrompere la trasmissione e avvisare l'utente.
+ Gli AirPods non registrano alcun audio se la categoria `AVAudioSession` è impostata su `record`. Per impostazione predefinita, l'SDK utilizza `playAndRecord`, quindi questo problema si manifesta solo se la categoria viene modificata in `record`.

  **Soluzione alternativa:** se è possibile che gli AirPods vengano utilizzati per registrare audio, utilizzare `playAndRecord` anche se l'applicazione non sta riproducendo file multimediali. 
+ Quando gli AirPods sono collegati a un dispositivo iOS 12, non è possibile utilizzare nessun altro microfono per registrare l'audio. Se si prova a passare a un microfono interno, si torna immediatamente agli AirPods.

  **Soluzione alternativa:** nessuna. Se gli AirPods sono collegati a iOS 12, sono l'unico dispositivo in grado di registrare audio.
+ L'invio di dati audio più velocemente rispetto al tempo reale (utilizzando una fonte audio personalizzata) determina la perdita di sincronizzazione dell'audio.

  **Soluzione alternativa:** non inviare dati audio a una velocità superiore al tempo reale. 
+ Gli artefatti audio possono apparire a bitrate inferiori a 68 kb/s quando si utilizza una frequenza di campionamento elevata (44.100 Hz o superiore) e due canali.

  **Soluzione alternativa:** aumentare il bitrate a 68 kb/s o superiore, diminuire la frequenza di campionamento a 24.000 Hz o inferiore o impostare i canali su 1.
+ Quando la cancellazione dell'eco è abilitata sui dispositivi `IVSMicrophone`, il metodo `listAvailableInputSources` restituisce solo una singola origine del microfono. 

  **Soluzione alternativa:** nessuna. Questo comportamento è controllato da iOS.
+ La modifica del routing audio Bluetooth può essere imprevedibile. Se si connette un nuovo dispositivo a metà sessione, iOS potrebbe cambiare o meno il routing di input in modo automatico. Inoltre, non è possibile scegliere tra più auricolari Bluetooth collegati contemporaneamente. Ciò accade sia nelle normali sessioni di trasmissione che in quelle relative allo stage.

  **Soluzione alternativa:** se si prevede di utilizzare un auricolare Bluetooth, collegarlo prima di avviare la trasmissione o lo stage e lasciarlo connesso per tutta la durata della sessione.
+ iOS rimuove l'accesso alla fotocamera quando appare il popup degli AirPods dopo aver aperto una custodia AirPods abbinata, lasciando gli AirPods nella custodia. Il risultato è il blocco del video di una trasmissione o del palco.

  **Soluzione alternativa:** nessuna. iOS revoca completamente l'accesso alla fotocamera durante il rendering del popup ed è impossibile per le applicazioni di terze parti impedirlo.
+ L'attivazione dei B-frame può migliorare la qualità della compressione; tuttavia alcuni codificatori forniscono un controllo del bitrate meno preciso quando i B-frame sono abilitati, il che può causare problemi durante le fluttuazioni della rete.

  **Soluzione alternativa:** considerare la possibilità di disattivare i B-frame se, per il caso d'uso specifico, l'aderenza costante del bitrate è più importante dell'efficienza di compressione.

# SDK di trasmissione IVS: Dispositivi misti
<a name="broadcast-mixed-devices"></a>

I dispositivi misti sono dispositivi audio e video che prendono più sorgenti di ingresso e generano una singola uscita. I dispositivi di mixaggio sono una potente funzionalità che consente di definire e gestire più elementi sullo schermo (video) e tracce audio. È possibile combinare video e audio da più sorgenti come fotocamere, microfoni, catture dello schermo e audio e video generati dall'app. È possibile utilizzare le transizioni per spostare queste sorgenti nel video trasmesso in streaming su IVS, nonché aggiungere e rimuovere sorgenti durante lo streaming.

I dispositivi misti sono disponibili nelle versioni audio e immagine. Per creare un dispositivo con immagini misto, chiamare:

`DeviceDiscovery.createMixedImageDevice()` su Android

`IVSDeviceDiscovery.createMixedImageDevice()` su iOS

Il dispositivo restituito può essere collegato a una `BroadcastSession` (streaming a bassa latenza) o `Stage` (streaming in tempo reale), come qualsiasi altro dispositivo.

## Terminologia
<a name="broadcast-mixed-devices-terminology"></a>

![\[Terminologia per i dispositivi misti per la trasmissione IVS.\]](http://docs.aws.amazon.com/it_it/ivs/latest/LowLatencyUserGuide/images/Broadcast_SDK_Mixer_Glossary.png)



| Termine | Descrizione | 
| --- | --- | 
| Dispositivo | Un componente hardware o software che produce input audio o immagine. Esempi di dispositivi sono microfoni, fotocamere, cuffie Bluetooth e dispositivi virtuali come catture di schermo o ingressi di immagini personalizzate. | 
| Dispositivi misti | Un `Device` che può essere collegato a una `BroadcastSession` come qualsiasi altro `Device`, ma con API aggiuntive che consentono di aggiungere oggetti `Source`. I dispositivi misti dispongono di mixer interni che combinano audio o immagini, producendo un unico flusso di audio e immagini in uscita. I dispositivi misti sono disponibili nelle versioni audio e immagine.  | 
| Configurazione del dispositivo misto | Un oggetto di configurazione per il dispositivo misto. Per i dispositivi con immagini miste, questa opzione configura proprietà quali dimensioni e framerate. Per i dispositivi audio misti, configura il numero di canali. | 
|  Origine | Un container che definisce la posizione di un elemento visivo sullo schermo e le proprietà di una traccia audio nel mix audio. Un dispositivo misto può essere configurato con zero o più sorgenti. Alle sorgenti viene assegnata una configurazione che influisce sul modo in cui vengono utilizzati i contenuti multimediali della sorgente. L'immagine qui sopra mostra quattro sorgenti di immagini: [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/it_it/ivs/latest/LowLatencyUserGuide/broadcast-mixed-devices.html)  | 
| Configurazione della sorgente |  Un oggetto di configurazione per la sorgente che entra in un dispositivo misto. Gli oggetti di configurazione completi sono descritti di seguito.   | 
| Transition | Per spostare uno slot in una nuova posizione o modificarne alcune proprietà, utilizza `MixedDevice.transitionToConfiguration()`. Questo metodo richiede: [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/it_it/ivs/latest/LowLatencyUserGuide/broadcast-mixed-devices.html) | 

## Dispositivo audio misto
<a name="broadcast-mixed-audio-device"></a>

### Configurazione
<a name="broadcast-mixed-audio-device-configuration"></a>

`MixedAudioDeviceConfiguration` su Android

`IVSMixedAudioDeviceConfiguration` su iOS


| Name | Tipo | Descrizione | 
| --- | --- | --- | 
| `channels` | Numero intero | Numero di canali di output dal mixer audio. Valori validi: 1, 2. Il canale 1 è audio mono mentre il canale 2 è audio stereo. Default: 2 | 

### Configurazione della sorgente
<a name="broadcast-mixed-audio-device-source-configuration"></a>

`MixedAudioDeviceSourceConfiguration` su Android

`IVSMixedAudioDeviceSourceConfiguration` su iOS


| Name | Tipo | Descrizione | 
| --- | --- | --- | 
| `gain` | Float | Guadagno audio. Questo è un moltiplicatore, quindi qualsiasi valore maggiore di 1 aumenta il guadagno e qualsiasi valore minore di 1 lo diminuisce. Valori validi: 0-2. Default: 1.  | 

## Dispositivo di immagine
<a name="broadcast-mixed-image-device"></a>

### Configurazione
<a name="broadcast-mixed-image-device-configuration"></a>

`MixedImageDeviceConfiguration` su Android

`IVSMixedImageDeviceConfiguration` su iOS


| Name | Tipo | Descrizione | 
| --- | --- | --- | 
| `size` | Vec2 | Dimensioni della tela video. | 
| `targetFramerate` | Numero intero | Il numero di frame di destinazione al secondo per il dispositivo misto. In media questo valore dovrebbe essere raggiunto, ma il sistema potrebbe perdere frame in determinate circostanze (ad esempio, con carico elevato della CPU o della GPU). | 
| `transparencyEnabled` | Booleano | Ciò consente la fusione utilizzando la proprietà `alpha` sulle configurazioni delle sorgenti delle immagini. L'impostazione di questa opzione su `true` aumenta il consumo di memoria e CPU. Impostazione predefinita: `false`. | 

### Configurazione della sorgente
<a name="broadcast-mixed-image-device-source-configuration"></a>

`MixedImageDeviceSourceConfiguration` su Android

`IVSMixedImageDeviceSourceConfiguration` su iOS


| Name | Tipo | Descrizione | 
| --- | --- | --- | 
| `alpha` | Float | L'alfa dello slot. Questo è un fattore moltiplicativo con qualsiasi valore alfa nell'immagine. Valori validi: 0-1, dove 0 è completamente trasparente e 1 è completamente opaco. Default: 1. | 
| `aspect` | AspectMode | La modalità proporzioni per qualsiasi immagine renderizzata nello slot. Valori validi: [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/it_it/ivs/latest/LowLatencyUserGuide/broadcast-mixed-devices.html) Impostazione predefinita: `Fit`  | 
| `fillColor` | Vec 4 | Il colore di riempimento da utilizzare con `aspect Fit` quando le proporzioni dello slot e dell'immagine non corrispondono. Il formato è (rosso, verde, blu, alfa). Valore valido (per ciascun canale): 0 - 1. Default: (0, 0, 0, 0). | 
| `position` | Vec2 | Posizione dello slot (in pixel) rispetto all'angolo superiore sinistro della tela. Anche l'origine dello slot è in alto a sinistra. | 
| `size` | Vec2 | Dimensioni dello slot, in pixel. L'impostazione di questo valore imposta anche `matchCanvasSize` su `false`. Default: (0, 0); tuttavia, perché `matchCanvasSize` di default è `true`, la dimensione renderizzata dello slot è la dimensione della tela, non (0, 0). | 
| `zIndex` | Float | Ordinamento relativo degli slot. Gli slot con valori `zIndex` più elevati sono disegnati sopra gli slot con valori `zIndex` minori. | 

## Creazione e configurazione di un dispositivo di immagini misto
<a name="broadcast-mixed-image-device-creating-configuring"></a>

![\[Configurazione di una sessione di tramissione per il mixaggio.\]](http://docs.aws.amazon.com/it_it/ivs/latest/LowLatencyUserGuide/images/Broadcast_SDK_Mixer_Configuring.png)


Qui creiamo una scena simile a quella all'inizio di questa guida, con tre elementi sullo schermo:
+ Slot in basso a sinistra per una fotocamera.
+ Slot in basso a destra per una sovrapposizione del logo.
+ Slot in alto a destra per un filmato.

Nota che l'origine della tela è l'angolo in alto a sinistra e questa è la stessa per gli slot. Quindi, posizionando uno slot in (0, 0) sarà posizionato nell'angolo in alto a sinistra con l'intero slot visibile.

### iOS
<a name="broadcast-mixed-image-device-creating-configuring-ios"></a>

```
let deviceDiscovery = IVSDeviceDiscovery()
let mixedImageConfig = IVSMixedImageDeviceConfiguration()
mixedImageConfig.size = CGSize(width: 1280, height: 720)
try mixedImageConfig.setTargetFramerate(60)
mixedImageConfig.isTransparencyEnabled = true
let mixedImageDevice = deviceDiscovery.createMixedImageDevice(with: mixedImageConfig)

// Bottom Left
let cameraConfig = IVSMixedImageDeviceSourceConfiguration()
cameraConfig.size = CGSize(width: 320, height: 180)
cameraConfig.position = CGPoint(x: 20, y: mixedImageConfig.size.height - cameraConfig.size.height - 20)
cameraConfig.zIndex = 2
let camera = deviceDiscovery.listLocalDevices().first(where: { $0 is IVSCamera }) as? IVSCamera
let cameraSource = IVSMixedImageDeviceSource(configuration: cameraConfig, device: camera)
mixedImageDevice.add(cameraSource)

// Top Right
let streamConfig = IVSMixedImageDeviceSourceConfiguration()
streamConfig.size = CGSize(width: 640, height: 320)
streamConfig.position = CGPoint(x: mixedImageConfig.size.width - streamConfig.size.width - 20, y: 20)
streamConfig.zIndex = 1
let streamDevice = deviceDiscovery.createImageSource(withName: "stream")
let streamSource = IVSMixedImageDeviceSource(configuration: streamConfig, device: streamDevice)
mixedImageDevice.add(streamSource)

// Bottom Right
let logoConfig = IVSMixedImageDeviceSourceConfiguration()
logoConfig.size = CGSize(width: 320, height: 180)
logoConfig.position = CGPoint(x: mixedImageConfig.size.width - logoConfig.size.width - 20,
                              y: mixedImageConfig.size.height - logoConfig.size.height - 20)
logoConfig.zIndex = 3
let logoDevice = deviceDiscovery.createImageSource(withName: "logo")
let logoSource = IVSMixedImageDeviceSource(configuration: logoConfig, device: logoDevice)
mixedImageDevice.add(logoSource)
```

### Android
<a name="broadcast-mixed-image-device-creating-configuring-android"></a>

```
val deviceDiscovery = DeviceDiscovery(this /* context */)
val mixedImageConfig = MixedImageDeviceConfiguration().apply {
    setSize(BroadcastConfiguration.Vec2(1280f, 720f))
    setTargetFramerate(60)
    setEnableTransparency(true)
}
val mixedImageDevice = deviceDiscovery.createMixedImageDevice(mixedImageConfig)

// Bottom Left
val cameraConfig = MixedImageDeviceSourceConfiguration().apply {
    setSize(BroadcastConfiguration.Vec2(320f, 180f))
    setPosition(BroadcastConfiguration.Vec2(20f, mixedImageConfig.size.y - size.y - 20))
    setZIndex(2)
}
val camera = deviceDiscovery.listLocalDevices().firstNotNullOf { it as? CameraSource }
val cameraSource = MixedImageDeviceSource(cameraConfig, camera)
mixedImageDevice.addSource(cameraSource)

// Top Right
val streamConfig = MixedImageDeviceSourceConfiguration().apply {
    setSize(BroadcastConfiguration.Vec2(640f, 320f))
    setPosition(BroadcastConfiguration.Vec2(mixedImageConfig.size.x - size.x - 20, 20f))
    setZIndex(1)
}
val streamDevice = deviceDiscovery.createImageInputSource(streamConfig.size)
val streamSource = MixedImageDeviceSource(streamConfig, streamDevice)
mixedImageDevice.addSource(streamSource)

// Bottom Right
val logoConfig = MixedImageDeviceSourceConfiguration().apply {
    setSize(BroadcastConfiguration.Vec2(320f, 180f))
    setPosition(BroadcastConfiguration.Vec2(mixedImageConfig.size.x - size.x - 20, mixedImageConfig.size.y - size.y - 20))
    setZIndex(1)
}
val logoDevice = deviceDiscovery.createImageInputSource(logoConfig.size)
val logoSource = MixedImageDeviceSource(logoConfig, logoDevice)
mixedImageDevice.addSource(logoSource)
```

## Rimozione delle sorgenti
<a name="broadcast-mixed-devices-removing-sources"></a>

Per rimuovere una sorgente, chiamare `MixedDevice.remove` con l'oggetto di `Source` che desideri rimuovere.

## Animazioni con transizioni
<a name="broadcast-mixed-devices-animations-transitions"></a>

Il metodo di transizione sostituisce la configurazione di una sorgente con una nuova configurazione. Questa sostituzione può essere animata nel tempo impostando una durata superiore a 0, in secondi. 

### Quali proprietà possono essere animate?
<a name="broadcast-mixed-devices-animations-properties"></a>

Non tutte le proprietà nella struttura dello slot possono essere animate. Qualsiasi proprietà basata su tipi Float può essere animata; altre proprietà hanno effetto all'inizio o alla fine dell'animazione.


| Name | Può essere animato? | Punto d'impatto | 
| --- | --- | --- | 
| `Audio.gain` | Sì | Interpolato | 
| `Image.alpha` | Sì | Interpolato | 
| `Image.aspect` | No | End | 
| `Image.fillColor` | Sì | Interpolato | 
| `Image.position` | Sì | Interpolato | 
| `Image.size` | Sì | Interpolato | 
| `Image.zIndex` Nota: `zIndex` sposta i piani 2D attraverso lo spazio 3D, quindi la transizione avviene quando i due piani si incrociano in un certo punto al centro dell'animazione. Questo potrebbe essere calcolato, ma dipende dai valori di `zIndex` di inizio e di fine. Per una transizione più fluida, combinalo con `alpha`.  | Sì | Sconosciuto | 

### Esempi semplici
<a name="broadcast-mixed-devices-animations-examples"></a>

Di seguito sono riportati esempi di acquisizione di una fotocamera a schermo intero utilizzando la configurazione definita in alto in [Creazione e configurazione di un dispositivo di immagini misto](#broadcast-mixed-image-device-creating-configuring). Questo è animato per 0,5 secondi.

#### iOS
<a name="broadcast-mixed-devices-animations-examples-ios"></a>

```
// Continuing the example from above, modifying the existing cameraConfig object.
cameraConfig.size = CGSize(width: 1280, height: 720)
cameraConfig.position = CGPoint.zero
cameraSource.transition(to: cameraConfig, duration: 0.5) { completed in
    if completed {
        print("Animation completed")
    } else {
        print("Animation interrupted")
    }
}
```

#### Android
<a name="broadcast-mixed-devices-animations-examples-android"></a>

```
// Continuing the example from above, modifying the existing cameraConfig object.
cameraConfig.setSize(BroadcastConfiguration.Vec2(1280f, 720f))
cameraConfig.setPosition(BroadcastConfiguration.Vec2(0f, 0f))
cameraSource.transitionToConfiguration(cameraConfig, 500) { completed ->
    if (completed) {
        print("Animation completed")
    } else {
        print("Animation interrupted")
    }
}
```

## Mirroring della trasmissione
<a name="broadcast-mixed-devices-mirroring"></a>


| Per eseguire il mirroring di un dispositivo immagine collegato nella trasmissione in questa direzione... | Usa un valore negativo per... | 
| --- | --- | 
| Orizzontalmente | La larghezza dello slot | 
| Verticalmente | L’altezza dello slot | 
| Sia orizzontalmente che verticalmente | Larghezza e altezza dello slot | 

La posizione dovrà essere regolata dello stesso valore per mettere lo slot nella posizione corretta quando viene eseguito il mirroring.

Di seguito sono riportati alcuni esempi di mirroring della trasmissione in orizzontale e in verticale.

### iOS
<a name="broadcast-mixed-devices-mirroring-ios"></a>

Mirroring orizzontale:

```
let cameraSource = IVSMixedImageDeviceSourceConfiguration()
cameraSource.size = CGSize(width: -320, height: 720)
// Add 320 to position x since our width is -320
cameraSource.position = CGPoint(x: 320, y: 0)
```

Mirroring verticale:

```
let cameraSource = IVSMixedImageDeviceSourceConfiguration()
cameraSource.size = CGSize(width: 320, height: -720)
// Add 720 to position y since our height is -720
cameraSource.position = CGPoint(x: 0, y: 720)
```

### Android
<a name="broadcast-mixed-devices-mirroring-android"></a>

Mirroring orizzontale:

```
val cameraConfig = MixedImageDeviceSourceConfiguration().apply {
    setSize(BroadcastConfiguration.Vec2(-320f, 180f))
   // Add 320f to position x since our width is -320f
    setPosition(BroadcastConfiguration.Vec2(320f, 0f))
}
```

Mirroring verticale:

```
val cameraConfig = MixedImageDeviceSourceConfiguration().apply {
    setSize(BroadcastConfiguration.Vec2(320f, -180f))
    // Add 180f to position y since our height is -180f
    setPosition(BroadcastConfiguration.Vec2(0f, 180f))
}
```

Nota: questo mirroring è diverso dal metodo `setMirrored` su `ImagePreviewView` (Android) e `IVSImagePreviewView` (iOS). Questo metodo influisce solo sulla visualizzazione dell'anteprima locale sul dispositivo e non ha alcun impatto sulla trasmissione.

# SDK di trasmissione IVS: origini di immagini personalizzate \$1 Streaming a bassa latenza
<a name="broadcast-custom-image-sources"></a>

Questa guida presuppone una certa familiarità con come configurare una sessione di trasmissione ([Android](broadcast-android.md), [iOS](broadcast-ios.md)) e come [utilizzare l'API di dispositivi misti](broadcast-mixed-devices.md).

Le sorgenti di input di immagini personalizzate consentono a un'applicazione di fornire il proprio input di immagini all'SDK di trasmissione, anziché limitarsi alle fotocamere preimpostate o alla condivisione dello schermo. Una sorgente di immagine personalizzata può essere semplice come una filigrana semitrasparente o una scena statica "torno subito" oppure può consentire all'app di eseguire ulteriori elaborazioni personalizzate come l'aggiunta di filtri di bellezza alla fotocamera.

È possibile avere più sorgenti di immagini personalizzate, come una filigrana e una fotocamera con filtri di bellezza. Quando si utilizza una sorgente di input di immagine personalizzata per il controllo personalizzato della fotocamera (ad esempio l'utilizzo di librerie di filtri estetici che richiedono l'accesso alla fotocamera), l'SDK di trasmissione non è più responsabile della gestione della fotocamera. Invece, l'applicazione è responsabile della corretta gestione del ciclo di vita della fotocamera. Consulta la documentazione ufficiale della piattaforma su come la tua applicazione dovrebbe gestire la fotocamera.

## Android
<a name="custom-image-sources-android"></a>

Dopo aver creato una sessione di trasmissione, crea una sorgente di input di immagine: 

```
SurfaceSource surfaceSource = broadcastSession.createImageInputSource();
```

Questo metodo restituisce un `SurfaceSource`, che è una sorgente immagine supportata da un [Surface](https://developer.android.com/reference/android/view/Surface) Android standard. Viene automaticamente collegato alla sessione di trasmissione, pertanto non è necessario utilizzare il metodo `attachDevice(...)` subito dopo. Tuttavia, il `SurfaceSource` deve essere legato a uno slot, operazione descritta più avanti di seguito. `SurfaceSource` può essere ridimensionato e ruotato. Puoi inoltre creare un `ImagePreviewView` per visualizzare un'anteprima del contenuto.

Per recuperare il sottostante `Surface`:

```
Surface surface = surfaceSource.getInputSurface();
```

Questo `Surface` può essere utilizzato come buffer di output per producer di immagini come Camera2, OpenGL ES e altre librerie. Il caso d'uso più semplice è disegnare direttamente una bitmap statica o un colore sulla tela di Surface. Tuttavia, molte librerie (come le librerie di filtri estetici) forniscono un metodo che consente a un'applicazione di specificare un `Surface` esterno per il rendering. È possibile utilizzare un metodo del genere per passare questo `Surface` alla libreria di filtri, il che consente alla libreria di emettere frame elaborati per lo streaming della sessione di trasmissione.

Infine, il `SurfaceSource` deve essere collegato a un `Mixer.Slot` da trasmettere in streaming dalla sessione di trasmissione:

```
broadcastSession.getMixer().bind(surfaceSource, "customSlot");
```

Il [codice di esempio Android](https://github.com/aws-samples/amazon-ivs-broadcast-android-sample) ha diversi esempi che utilizzano una sorgente di immagine personalizzata in diversi modi:
+ Viene aggiunta una filigrana semitrasparente in `MixerActivity`.
+ Un file MP4 viene eseguito in loop in `MixerActivity`.
+ La classe di utilità [Camera Manager](https://github.com/aws-samples/amazon-ivs-broadcast-android-sample/blob/main/app/src/main/java/com/amazonaws/ivs/basicbroadcast/common/CameraManager.kt) esegue la gestione personalizzata della fotocamera del dispositivo utilizzando il metodo Camera2 in `CustomActivity`, che applica un semplice filtro seppia. Questo esempio è particolarmente utile in quanto mostra come gestire la fotocamera e passare il `SurfaceSource` personalizzato della sessione di trasmissione alla richiesta di acquisizione della fotocamera. Se utilizzi altre librerie esterne, consulta la documentazione su come configurare la libreria per l'output su `Surface` Android fornito dalla sessione di trasmissione.

## iOS
<a name="custom-image-sources-ios"></a>

Dopo aver creato una sessione di trasmissione, crea una sorgente di input di immagine:

```
let customSource = broadcastSession.createImageSource(withName: "customSourceName")
```

Questo metodo restituisce un `IVSCustomImageSource`, che è una fonte di immagini che consente alla domanda di inviare `CMSampleBuffers` manualmente. Per i formati pixel supportati, consulta Riferimento all'SDK di trasmissione iOS; un collegamento alla versione più recente è presente nel manuale [Note di rilascio di Amazon IVS](release-notes.md) per l'ultima versione dell'SDK di trasmissione. La sorgente non è collegata automaticamente alla sessione di trasmissione, quindi è necessario collegare la sorgente dell'immagine alla sessione e collegarla a uno slot prima che possa essere trasmessa in streaming:

```
broadcastSession.attach(customSource, toSlotWithName: "customSourceSlot", onComplete: nil)
```

Dopo che l'origine personalizzata è stata collegata e associata, l'applicazione può inviare `CMSampleBuffers` direttamente alla fonte personalizzata. È possibile scegliere di utilizzare la richiamata `onComplete` per iniziare a farlo.

I campioni inviati alla sorgente personalizzata verranno trasmessi in streaming nella sessione di trasmissione:

```
customSource.onSampleBuffer(sampleBuffer)
```

Per lo streaming di video, utilizzare questo metodo in una richiamata. Ad esempio, se si utilizza la fotocamera, ogni volta che viene ricevuto un nuovo buffer campione da un `AVCaptureSession`, l'applicazione può inoltrare il buffer campione alla sorgente di immagine personalizzata. Se lo desideri, l'applicazione può applicare ulteriori elaborazioni (come un filtro di bellezza) prima di inviare il campione alla sorgente di immagine personalizzata.

Per un'immagine statica, dopo il primo campione, l'applicazione deve inviare nuovamente il campione se l'associazione dello slot della sorgente di immagine personalizzata viene modificata o se la sorgente viene staccata e ricollegata alla sessione di trasmissione. Ad esempio, se si rimuove lo slot e lo si riaggiunge al mixer, è necessario inviare nuovamente il campione.

L'[app di esempio iOS](https://github.com/aws-samples/amazon-ivs-broadcast-ios-sample) ha diversi esempi che utilizzano una sorgente di immagine personalizzata in diversi modi:
+ Viene aggiunta una filigrana semitrasparente in `MixerViewController`.
+ Un file MP4 viene eseguito in loop in `MixerViewController`.
+ Un'implementazione CIFilter con una fotocamera del dispositivo è stata aggiunta in `CustomSourcesViewController`. Ciò consente a un'applicazione di gestire una fotocamera del dispositivo indipendentemente dall'SDK Amazon IVS Broadcast. Usa `AVCaptureSession` per acquisire un'immagine dalla fotocamera del dispositivo, elabora l'immagine utilizzando un'implementazione CIFilter e invia `CMSampleBuffers` a `customSource` per lo streaming live.