Delen via


JavaScript-zelfstudie: Een bestand uploaden en analyseren met Azure Functions en Blob Storage

In deze zelfstudie leert u hoe u een afbeelding uploadt naar Azure Blob Storage en deze verwerkt met behulp van Azure Functions, Computer Vision en Cosmos DB. U leert ook hoe u Azure Function-triggers en -bindingen implementeert als onderdeel van dit proces. Samen analyseren deze services een geüploade afbeelding die tekst bevat, extraheert u de tekst eruit en slaat u de tekst vervolgens op in een databaserij voor latere analyse of andere doeleinden.

Azure Blob Storage is de zeer schaalbare oplossing voor objectopslag van Microsoft voor de cloud. Blob Storage is ontworpen voor het opslaan van afbeeldingen en documenten, het streamen van mediabestanden, het beheren van back-up- en archiefgegevens en nog veel meer. Meer informatie over Blob Storage vindt u op de overzichtspagina.

Waarschuwing

Deze zelfstudie is bedoeld voor snelle acceptatie en voldoet daarom niet aan de standaardvereisten voor veilig gebruik. Als u meer wilt weten over dit scenario met een standaarddoel, gaat u naar Beveiligingsoverwegingen.

Azure Cosmos DB is een volledig beheerde NoSQL- en relationele database voor het ontwikkelen van moderne apps.

Azure Functions is een serverloze computeroplossing waarmee u kleine codeblokken kunt schrijven en uitvoeren als zeer schaalbare, serverloze, gebeurtenisgestuurde functies. Meer informatie over Azure Functions vindt u op de overzichtspagina.

In deze zelfstudie leert u het volgende:

  • Afbeeldingen en bestanden uploaden naar Blob Storage
  • Een Azure Function-gebeurtenistrigger gebruiken om gegevens te verwerken die zijn geüpload naar Blob Storage
  • Azure AI-services gebruiken om een afbeelding te analyseren
  • Gegevens schrijven naar Cosmos DB met behulp van Uitvoerbindingen van Azure Function

Architectuurdiagram met een afbeeldingsblob wordt toegevoegd aan Blob Storage en vervolgens geanalyseerd door een Azure-functie, waarbij de analyse is ingevoegd in een Cosmos DB.

Vereisten

Het opslagaccount en de container maken

De eerste stap is het maken van het opslagaccount waarin de geüploade blobgegevens worden opgeslagen. In dit scenario zijn dit afbeeldingen die tekst bevatten. Een opslagaccount biedt verschillende services, maar deze zelfstudie maakt alleen gebruik van Blob Storage.

  1. Selecteer Ctrl + Shift + P in Visual Studio Code om het opdrachtenpalet te openen.

  2. Zoek naar Azure Storage: Opslagaccount maken (geavanceerd).

  3. Gebruik de volgende tabel om de opslagresource te maken.

    Instelling Weergegeven als
    Naam Voer msdocsstoragefunction of iets dergelijks in.
    Resourcegroep Maak de msdocs-storage-function resourcegroep die u eerder hebt gemaakt.
    Statische webhosting Nee
  4. Selecteer Shift + Alt + A in Visual Studio Code om Azure Explorer te openen.

  5. Vouw de sectie Opslag uit, vouw het abonnementsknooppunt uit en wacht tot de resource is gemaakt.

De container maken in Visual Studio Code

  1. Vouw in Azure Explorer de nieuwe opslagresource uit om de knooppunten te zien.
  2. Klik met de rechtermuisknop op BlobContainers en selecteer BlobContainer maken.
  3. Voer de naam images in. Hiermee maakt u een privécontainer.

Overstappen van privé naar openbare container in Azure Portal

In deze procedure wordt een openbare container verwacht. Als u deze configuratie wilt wijzigen, moet u de wijziging aanbrengen in Azure Portal.

  1. Klik met de rechtermuisknop op de opslagresource in Azure Explorer en selecteer Openen in de portal.
  2. Selecteer Containers in de sectie Gegevensopslag.
  3. Zoek uw container imagesen selecteer het ... (beletselteken) aan het einde van de regel.
  4. Selecteer Toegangsniveau wijzigen.
  5. Selecteer Blob (anonieme leestoegang voor blobs en selecteer vervolgens OK.
  6. Ga terug naar Visual Studio Code.

De verbindingsreeks ophalen in Visual Studio Code

  1. Selecteer Shift + Alt + A in Visual Studio Code om Azure Explorer te openen.
  2. Klik met de rechtermuisknop op uw opslagresource en selecteer Verbindingsreeks kopiëren.
  3. plak deze ergens om later te gebruiken.
  4. Noteer ook de naam msdocsstoragefunction van het opslagaccount dat u later wilt gebruiken.

De Azure AI Vision-service maken

Maak vervolgens het Azure AI Vision-serviceaccount waarmee de geüploade bestanden worden verwerkt. Vision maakt deel uit van Azure AI-services en biedt verschillende functies voor het extraheren van gegevens uit afbeeldingen. Meer informatie over Azure AI Vision vindt u op de overzichtspagina.

  1. Zoek in de zoekbalk boven aan de portal naar Computer en selecteer het resultaat met het label Computer Vision.

  2. Selecteer + Maken op de computer vision-pagina.

  3. Voer op de pagina Computer Vision maken de volgende waarden in:

    • Abonnement: kies uw gewenste abonnement.
    • Resourcegroep: gebruik de msdocs-storage-function resourcegroep die u eerder hebt gemaakt.
    • Regio: Selecteer de regio die zich het dichtst bij u bevindt.
    • Naam: Voer een naam in van msdocscomputervision.
    • Prijscategorie: Kies Gratis als deze beschikbaar is, kies anders Standard S1.
    • Schakel het selectievakje Verantwoordelijke AI-kennisgeving in als u akkoord gaat met de voorwaarden

    Een schermopname die laat zien hoe u een nieuwe Computer Vision-service maakt.

  4. Selecteer Beoordelen en maken onderaan. Het duurt even voordat Azure de gegevens valideert die u hebt ingevoerd. Zodra de instellingen zijn gevalideerd, kiest u Maken en Azure begint met het inrichten van de Computer Vision-service. Dit kan even duren.

  5. Wanneer de bewerking is voltooid, selecteert u Ga naar resource.

De Computer Vision-sleutels ophalen

Vervolgens moeten we de geheime sleutel en eindpunt-URL vinden voor de Computer Vision-service die moet worden gebruikt in onze Azure Function-app.

  1. Selecteer sleutels en eindpunt op de overzichtspagina van Computer Vision.

  2. Kopieer op de pagina Sleutels en Eindpunt de waarde sleutel 1 en de endPoint-waarden en plak deze ergens om later te gebruiken. Het eindpunt moet de indeling hebben van https://YOUR-RESOURCE-NAME.cognitiveservices.azure.com/

Een schermopname die laat zien hoe u het sleutels- en URL-eindpunt voor een Computer Vision-service ophaalt.

Een Cosmos DB-serviceaccount maken

Maak het Cosmos DB-serviceaccount om de analyse van bestanden op te slaan. Azure Cosmos DB is een volledig beheerde NoSQL- en relationele database voor het ontwikkelen van moderne apps. Meer informatie over Cosmos DB en de bijbehorende ondersteunings-API's voor verschillende branchedatabases.

Hoewel in deze zelfstudie een API wordt opgegeven wanneer u uw resource maakt, worden de Azure Function-bindingen voor Cosmos DB op dezelfde manier geconfigureerd voor alle Cosmos DB-API's.

  1. Zoek in de zoekbalk boven aan de portal naar Azure Cosmos DB en selecteer het resultaat.

  2. Selecteer + Maken op de pagina Azure Cosmos DB. Selecteer Azure Cosmos DB for NoSQL in de lijst met API-opties.

  3. Voer op de pagina Cosmos DB maken de volgende waarden in:

    • Abonnement: kies uw gewenste abonnement.
    • Resourcegroep: gebruik de msdocs-storage-function resourcegroep die u eerder hebt gemaakt.
    • Regio: Selecteer dezelfde regio als uw resourcegroep.
    • Naam: Voer een naam in van msdocscosmosdb.
    • Prijscategorie: Kies Gratis als deze beschikbaar is, kies anders Standard S1.
  4. Selecteer Beoordelen en maken onderaan. Het duurt even voordat Azure de gegevens valideert die u hebt ingevoerd. Zodra de instellingen zijn gevalideerd, kiest u Maken en Azure begint met het inrichten van de Computer Vision-service. Dit kan even duren.

  5. Wanneer de bewerking is voltooid, selecteert u Ga naar resource.

  6. Selecteer Data Explorer en selecteer vervolgens Nieuwe container.

  7. Maak een nieuwe database en container met de volgende instellingen:

    • Nieuwe database-id maken: StorageTutorial.
    • Voer de nieuwe container-id in: analysis.
    • Voer de partitiesleutel in: /type.
  8. Laat de rest van de standaardinstellingen staan en selecteer OK.

De Cosmos DB-verbindingsreeks ophalen

Haal de verbindingsreeks voor het Cosmos DB-serviceaccount op voor gebruik in onze Azure Function-app.

  1. Selecteer Sleutels op de overzichtspagina van Cosmos DB.

  2. Kopieer op de pagina Sleutels de primaire verbindingsreeks die u later wilt gebruiken.

Het voorbeeldproject downloaden en configureren

De code voor de Azure-functie die in deze zelfstudie wordt gebruikt, vindt u in deze GitHub-opslagplaats in de JavaScript-v4 submap. U kunt het project ook klonen met behulp van de onderstaande opdracht.

git clone https://github.com/Azure-Samples/msdocs-storage-bind-function-service.git \
cd msdocs-storage-bind-function-service/javascript-v4 \
code .

In het voorbeeldproject worden de volgende taken uitgevoerd:

  • Haalt omgevingsvariabelen op om verbinding te maken met het opslagaccount, Computer Vision en de Cosmos DB-service
  • Accepteert het geüploade bestand als blobparameter
  • Analyseert de blob met behulp van de Computer Vision-service
  • Hiermee voegt u de geanalyseerde afbeeldingstekst, als een JSON-object, in Cosmos DB in met behulp van uitvoerbindingen

Nadat u het project hebt gedownload en geopend, zijn er enkele essentiële concepten die u moet begrijpen:

Concept Doel
Functie De Azure-functie wordt gedefinieerd door zowel de functiecode als de bindingen. Deze bevinden zich in ./src/functions/process-blobs.js.
Triggers en bindingen De triggers en bindingen geven aan dat gegevens, die naar of buiten de functie worden verwacht en welke service die gegevens gaat verzenden of ontvangen.

Triggers en bindingen die in deze zelfstudie worden gebruikt om het ontwikkelingsproces uit te breiden door de noodzaak om code te schrijven om verbinding te maken met services te verwijderen.

Invoerblobtrigger voor opslag

De code, die aangeeft dat de functie wordt geactiveerd wanneer een blob wordt geüpload naar de installatiekopieëncontainer , volgt. De functie wordt geactiveerd op elke blobnaam, inclusief hiërarchische mappen.


// ...preceding code removed for brevity

app.storageBlob('process-blob-image', { 
    path: 'images/{name}',                // Storage container name: images, Blob name: {name}
    connection: 'StorageConnection',      // Storage account connection string
    handler: async (blob, context) => {

// ... function code removed for brevity
  • app.storageBlob: de invoertrigger voor opslagblob wordt gebruikt om de functie te binden aan de uploadgebeurtenis in Blob Storage. De trigger heeft twee vereiste parameters:
    • path: Het pad dat door de trigger wordt gecontroleerd op gebeurtenissen. Het pad bevat de containernaamimages en de variabele vervangen door de blobnaam. Deze blobnaam wordt opgehaald uit de name eigenschap.
    • {name}: De naam van de geüploade blob. Het gebruik van de blob parameter is de parameternaam voor de blob die in de functie komt. Wijzig de waarde blobniet.
    • connection: de verbindingsreeks van het opslagaccount. De waarde StorageConnection komt overeen met de naam in het bestand bij het local.settings.json lokaal ontwikkelen.

Cosmos DB-trigger uitvoeren

Wanneer de functie is voltooid, gebruikt de functie het geretourneerde object als de gegevens die moeten worden ingevoegd in Cosmos DB.


// ... function definition ojbect
app.storageBlob('process-blob-image', { 
    
        // removed for brevity    
        
        // Data to insert into Cosmos DB
        const id = uuidv4().toString();
        const analysis = await analyzeImage(blobUrl);
        
        // `type` is the partition key 
        const dataToInsertToDatabase = {
                id,
                type: 'image',
                blobUrl,
                blobSize: blob.length,
                analysis,
                trigger: context.triggerMetadata
            }

        return dataToInsertToDatabase;
    }),

    // Output binding for Cosmos DB
    return: output.cosmosDB({
        connection: 'CosmosDBConnection',
        databaseName:'StorageTutorial',
        containerName:'analysis'
    })
});

Voor de container in dit artikel zijn de volgende vereiste eigenschappen:

  • id: de id die is vereist voor Cosmos DB om een nieuwe rij te maken.

  • /type: de partitiesleutel die is opgegeven met de container is gemaakt.

  • output.cosmosDB : de Cosmos DB-uitvoertrigger wordt gebruikt om het resultaat van de functie in te voegen in Cosmos DB.

    • connection: de verbindingsreeks van het opslagaccount. De waarde StorageConnection komt overeen met de naam in het local.settings.json bestand.
    • databaseName: De Cosmos DB-database waarmee verbinding moet worden gemaakt.
    • containerName: De naam van de tabel om de geparseerde tekstwaarde voor de afbeelding te schrijven die door de functie wordt geretourneerd. De tabel moet al bestaan.

Azure Function-code

Hier volgt de volledige functiecode.

const { app, input, output } = require('@azure/functions');
const { v4: uuidv4 } = require('uuid');
const { ApiKeyCredentials } = require('@azure/ms-rest-js');
const { ComputerVisionClient } = require('@azure/cognitiveservices-computervision');
const sleep = require('util').promisify(setTimeout);

const STATUS_SUCCEEDED = "succeeded";
const STATUS_FAILED = "failed"

const imageExtensions = ["jpg", "jpeg", "png", "bmp", "gif", "tiff"];

async function analyzeImage(url) {

    try {

        const computerVision_ResourceKey = process.env.ComputerVisionKey;
        const computerVision_Endpoint = process.env.ComputerVisionEndPoint;

        const computerVisionClient = new ComputerVisionClient(
            new ApiKeyCredentials({ inHeader: { 'Ocp-Apim-Subscription-Key': computerVision_ResourceKey } }), computerVision_Endpoint);

        const contents = await computerVisionClient.analyzeImage(url, {
            visualFeatures: ['ImageType', 'Categories', 'Tags', 'Description', 'Objects', 'Adult', 'Faces']
        });

        return contents;

    } catch (err) {
        console.log(err);
    }
}
app.storageBlob('process-blob-image', { 
    path: 'images/{name}',
    connection: 'StorageConnection',
    handler: async (blob, context) => {

        context.log(`Storage blob 'process-blob-image' url:${context.triggerMetadata.uri}, size:${blob.length} bytes`);

        const blobUrl = context.triggerMetadata.uri;
        const extension = blobUrl.split('.').pop();

        if(!blobUrl) {
            // url is empty
            return;
        } else if (!extension || !imageExtensions.includes(extension.toLowerCase())){
            // not processing file because it isn't a valid and accepted image extension
            return;
        } else {
            //url is image
            const id = uuidv4().toString();
            const analysis = await analyzeImage(blobUrl);
            
            // `type` is the partition key 
            const dataToInsertToDatabase = {
                    id,
                    type: 'image',
                    blobUrl,
                    blobSize: blob.length,
                    ...analysis,
                    trigger: context.triggerMetadata
                }

            return dataToInsertToDatabase;
        }

        
    },
    return: output.cosmosDB({
        connection: 'CosmosDBConnection',
        databaseName:'StorageTutorial',
        containerName:'analysis'
    })
});

Met deze code worden ook essentiële configuratiewaarden opgehaald uit omgevingsvariabelen, zoals de Blob Storage-verbindingsreeks- en Computer Vision-sleutel. Deze omgevingsvariabelen worden toegevoegd aan de Azure Function-omgeving nadat deze is geïmplementeerd.

De standaardfunctie maakt ook gebruik van een tweede methode met de naam AnalyzeImage. Deze code maakt gebruik van het URL-eindpunt en de sleutel van het Computer Vision-account om een aanvraag te doen bij Computer Vision om de afbeelding te verwerken. De aanvraag retourneert alle tekst die in de afbeelding is gedetecteerd. Deze tekst wordt naar Cosmos DB geschreven met behulp van de uitgaande binding.

Lokale instellingen configureren

Als u het project lokaal wilt uitvoeren, voert u de omgevingsvariabelen in het ./local.settings.json bestand in. Vul de waarden van de tijdelijke aanduidingen in met de waarden die u eerder hebt opgeslagen bij het maken van de Azure-resources.

Hoewel de Azure Function-code lokaal wordt uitgevoerd, maakt deze verbinding met de cloudservices voor Opslag in plaats van lokale emulators te gebruiken.

{
  "IsEncrypted": false,
  "Values": {
    "FUNCTIONS_WORKER_RUNTIME": "node",
    "AzureWebJobsStorage": "",
    "StorageConnection": "STORAGE-CONNECTION-STRING",
    "StorageAccountName": "STORAGE-ACCOUNT-NAME",
    "StorageContainerName": "STORAGE-CONTAINER-NAME",
    "ComputerVisionKey": "COMPUTER-VISION-KEY",
    "ComputerVisionEndPoint":  "COMPUTER-VISION-ENDPOINT",
    "CosmosDBConnection": "COSMOS-DB-CONNECTION-STRING"
  }
}

Een Azure Functions-app maken

U bent nu klaar om de toepassing in Azure te implementeren met behulp van een Visual Studio Code-extensie.

  1. Selecteer Shift + Alt + A in Visual Studio Code om Azure Explorer te openen.

  2. Zoek en klik in de sectie Functions met de rechtermuisknop op het abonnement en selecteer Functie-app maken in Azure (geavanceerd).

  3. Gebruik de volgende tabel om de functieresource te maken.

    Instelling Weergegeven als
    Naam Voer msdocprocessimage of iets dergelijks in.
    Runtimestack Selecteer een Node.js LTS-versie .
    Programmeermodel Selecteer v4.
    Besturingssysteem Selecteer Linux.
    Resourcegroep Kies de msdocs-storage-function resourcegroep die u eerder hebt gemaakt.
    Location Selecteer dezelfde regio als uw resourcegroep.
    Abonnemtsype Selecteer Verbruik.
    Azure Storage Selecteer het opslagaccount dat u eerder hebt gemaakt.
    Application Insights Ga nu verder.
  4. Azure richt de aangevraagde resources in. Dit kan even duren.

Azure Functions-app implementeren

  1. Wanneer het vorige proces voor het maken van resources is voltooid, klikt u met de rechtermuisknop op de nieuwe resource in de sectie Functions van Azure Explorer en selecteert u Implementeren in functie-app.
  2. Als u wordt gevraagd of u zeker weet dat u wilt implementeren..., selecteert u Implementeren.
  3. Wanneer het proces is voltooid, wordt er een melding weergegeven met een keuze, waaronder uploadinstellingen. Selecteer deze optie. Hiermee worden de waarden uit uw local.settings.json-bestand gekopieerd naar uw Azure Function-app. Als de melding is verdwenen voordat u deze kon selecteren, gaat u verder met de volgende sectie.

App-instellingen toevoegen voor Storage en Computer Vision

Als u instellingen voor uploaden hebt geselecteerd in de melding, slaat u deze sectie over.

De Azure-functie is geïmplementeerd, maar kan nog geen verbinding maken met onze Opslagaccount- en Computer Vision-services. De juiste sleutels en verbindingsreeks s moeten eerst worden toegevoegd aan de configuratie-instellingen van de Azure Functions-app.

  1. Zoek uw resource in de sectie Functions van Azure Explorer, klik met de rechtermuisknop op Toepassingsinstellingen en selecteer Nieuwe instelling toevoegen.

  2. Voer een nieuwe app-instelling in voor de volgende geheimen. Kopieer en plak uw geheime waarden uit uw lokale project in het local.settings.json bestand.

    Instelling
    StorageConnection
    StorageAccountName
    StorageContainerName
    ComputerVisionKey
    ComputerVisionEndPoint
    CosmosDBConnection

Alle vereiste omgevingsvariabelen om onze Azure-functie te verbinden met verschillende services zijn nu aanwezig.

Een afbeelding uploaden naar Blob Storage

U bent nu klaar om onze toepassing te testen. U kunt een blob uploaden naar de container en vervolgens controleren of de tekst in de afbeelding is opgeslagen in Cosmos DB.

  1. Zoek in Azure Explorer in Visual Studio Code uw opslagresource en vouw deze uit in de sectie Storage .
  2. Vouw BlobContainers uit en klik met de rechtermuisknop op de containernaam en imagesselecteer Bestanden uploaden.
  3. U vindt een aantal voorbeeldafbeeldingen die zijn opgenomen in de map afbeeldingen in de hoofdmap van het downloadbare voorbeeldproject of u kunt een van uw eigen afbeeldingen gebruiken.
  4. Accepteer voor de doelmap de standaardwaarde. /
  5. Wacht totdat de bestanden zijn geüpload en vermeld in de container.

Tekstanalyse van afbeelding weergeven

Vervolgens kunt u controleren of de upload de Azure-functie heeft geactiveerd en of de tekst in de afbeelding correct is geanalyseerd en opgeslagen in Cosmos DB.

  1. Selecteer in Visual Studio Code, in Azure Explorer, onder het Azure Cosmos DB-knooppunt, uw resource en vouw deze uit om uw database, StorageTutorial, te vinden.

  2. Vouw het databaseknooppunt uit.

  3. Er moet nu een analysecontainer beschikbaar zijn. Selecteer op het knooppunt Documenten van de container om een voorbeeld van de gegevens in de container te bekijken. U ziet nu een vermelding voor de verwerkte afbeeldingstekst van een geüpload bestand.

    {
        "id": "3cf7d6f0-a362-421e-9482-3020d7d1e689",
        "type": "image",
        "blobUrl": "https://msdocsstoragefunction.blob.core.windows.net/images/presentation.png",
        "blobSize": 1383614,
        "analysis": {  ... details removed for brevity ...
            "categories": [],
            "adult": {},
            "imageType": {},
            "tags": [],
            "description": {},
            "faces": [],
            "objects": [],
            "requestId": "eead3d60-9905-499c-99c5-23d084d9cac2",
            "metadata": {},
            "modelVersion": "2021-05-01"
        },
        "trigger": { 
            "blobTrigger": "images/presentation.png",
            "uri": "https://msdocsstorageaccount.blob.core.windows.net/images/presentation.png",
            "properties": {
                "lastModified": "2023-07-07T15:32:38+00:00",
                "createdOn": "2023-07-07T15:32:38+00:00",
                "metadata": {},
                ... removed for brevity ...
                "contentLength": 1383614,
                "contentType": "image/png",
                "accessTier": "Hot",
                "accessTierInferred": true,
            },
            "metadata": {},
            "name": "presentation.png"
        },
        "_rid": "YN1FAKcZojEFAAAAAAAAAA==",
        "_self": "dbs/YN1FAA==/colls/YN1FAKcZojE=/docs/YN1FAKcZojEFAAAAAAAAAA==/",
        "_etag": "\"7d00f2d3-0000-0700-0000-64a830210000\"",
        "_attachments": "attachments/",
        "_ts": 1688743969
    }
    

Gefeliciteerd U hebt een afbeelding verwerkt die is geüpload naar Blob Storage met behulp van Azure Functions en Computer Vision.

Probleemoplossing

Gebruik de volgende tabel om problemen tijdens deze procedure op te lossen.

Verzenden Oplossing
await computerVisionClient.read(url); fouten met Only absolute URLs are supported Zorg ervoor dat uw ComputerVisionEndPoint eindpunt de indeling van https://YOUR-RESOURCE-NAME.cognitiveservices.azure.com/.

Beveiligingsoverwegingen

Deze oplossing, als zelfstudie voor beginners, demonstreert geen standaardprocedures voor beveiliging. Dit is bedoeld om u in staat te stellen de oplossing te implementeren. De volgende stap na die geslaagde implementatie is het beveiligen van de resources. Deze oplossing maakt gebruik van drie Azure-services, elk heeft zijn eigen beveiligingsfuncties en overwegingen voor standaardconfiguratie:

Voorbeeldcode

Resources opschonen

Als u deze toepassing niet meer gaat gebruiken, kunt u de resources verwijderen die u hebt gemaakt door de resourcegroep te verwijderen.

  1. Resourcegroepen selecteren in Azure Explorer
  2. Zoek en klik met de rechtermuisknop op de msdocs-storage-function resourcegroep in de lijst.
  3. Selecteer Verwijderen. Het verwijderen van de resourcegroep kan enkele minuten duren.