Skip to content

Commit

Permalink
[ADD] Folder containing cloud_analysis scripts
Browse files Browse the repository at this point in the history
  • Loading branch information
BenCretois committed Sep 29, 2023
1 parent 96f8eb8 commit 5bf8189
Show file tree
Hide file tree
Showing 3 changed files with 216 additions and 0 deletions.
33 changes: 33 additions & 0 deletions cloud_analysis/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
FROM python:3.8-bullseye

ARG PACKAGES="ffmpeg build-essential unzip gcsfuse"

ARG DEBIAN_FRONTEND=noninteractive
RUN \
echo "deb https://packages.cloud.google.com/apt gcsfuse-bullseye main" | tee /etc/apt/sources.list.d/gcsfuse.list && \
curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add - && \
apt-get update && \
apt-get install -qq $PACKAGES && \
rm -rf /var/lib/apt/lists/*

RUN pip3 install poetry

WORKDIR /app

# Clone the repository and download assets
RUN mkdir audioclip
RUN cd audioclip
RUN wget https://zenodo.org/record/7969521/files/assets.zip?download=1
RUN unzip ./assets.zip?download=1
RUN cd ../

# Package install
COPY . ./
RUN poetry config virtualenvs.create false
RUN poetry install --no-root



ENV PYTHONPATH "${PYTHONPATH}:/app:/app/audioclip:/app:/app/src"
ENTRYPOINT ["python", "/app/cloud_analysis/main.py"]

64 changes: 64 additions & 0 deletions cloud_analysis/instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
# Documentation on running a Docker container on google cloud

## General stuff with GCloud UI

- If lost, there is a button `console` on the upper right corner that brings us back to the projects


## Login stuff

1- Generate the Google Cloud credentials:

```
gcloud auth application-default login
```

The credentials are stored in `~/.config/gcloud/`

2- Login to your Google Cloud account:

```
gcloud auth login
```

3- Log in to the project

```
gcloud config set project snokuter-akustikk
```

## Docker stuff

1- Enable services

Enable the Cloud Functions, Cloud Run, and Cloud Build APIs:

```
gcloud services enable cloudfunctions.googleapis.com
gcloud services enable run.googleapis.com
gcloud services enable cloudbuild.googleapis.com
```

2- Set up credentials on Google Cloud:

The credentials are stored in `~/.docker/config.json`

```
gcloud auth configure-docker
```

3- Change the name of the image to push it on GCloud

The Docker image will be saved in Google's container registry, which is directly supported by Cloud Run

```
docker tag ghcr.io/ninanor/snowmobile_analyzer:main gcr.io/snoskuter-akustikk/snowmobile_analyzer:main
docker push gcr.io/snoskuter-akustikk/snowmobile_analyzer:main
```

4- Deploy the Docker image to Google Cloud run

```
gcloud run deploy model --image gcr.io/snoskuter-akustikk/snowmobile_analyzer:main
```
119 changes: 119 additions & 0 deletions cloud_analysis/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@

#!/usr/env/bin python3

from flask import Flask, request, jsonify
app = Flask(__name__)

import argparse
import numpy as np

import torch
from torch.utils.data import DataLoader

from predict import predict
from predict import initModel
from utils.utils import AudioList


def analyseAudioFile(
audio_file_path, batch_size=1, num_workers=4, min_hr = 0.1, min_conf = 0.99
):
# Initiate model
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model_path = "./assets/snowmobile_model.pth"
model = initModel(model_path=model_path, device=device)

# Run the predictions
list_preds = AudioList().get_processed_list(audio_file_path)
predLoader = DataLoader(list_preds, batch_size=batch_size, num_workers=num_workers, pin_memory=False)
prob_audioclip_array, hr_array = predict(predLoader, model, device)

# Set index of the array to 0 (beginning)
idx_begin = 0

# List of results
results = []

for item_audioclip, item_hr in zip(prob_audioclip_array, hr_array):

# Get the properties of the detection (start, end, label, confidence and harmonic ratio)
idx_end = idx_begin + 3
conf = np.array(item_audioclip)
label = np.argmax(conf, axis=0)
confidence = conf.max()
hr = np.array(item_hr)

# If the label is not "soundscape" then write the row:
if label != 0 and hr > min_hr and confidence > min_conf:
item_properties = [idx_begin, idx_end, confidence, hr]
results.append(item_properties)

# Update the start time of the detection
idx_begin = idx_end

return results

def on_process_audio(
audio_id: str, audio_rec: dict, audio_file_path: str
):

print(f"PROCESSING audioId={audio_id}")
location = audio_rec["location"]

# A call out to your code here. Optionally we can pass on the recorder coordinates
results = analyseAudioFile(audio_file_path)
# The object results is a list containing detections in the form:
# [start, end, confidence, harmonic ratio]

# After processing we record each detection in the database.
# Each detection should have a start and end time which is used to create an audio clip later.
detections = []
for r in results:
start, end, confidence, harmonic_ratio = r
# create the detections
detections.append({
u"start": start,
u"end": end,
u"tags": ["snowmobile"],
#u"analysisId": analysis_id,
# Add any other information you want to record here
u"confidence": confidence,
u"harmonic_ratio": harmonic_ratio
})

print(detections)
print(f"{audio_id} completed with {len(detections)} detections")


@app.route('/process-audio', methods=['POST'])
def process_audio_endpoint():
audio_file_path = request.json['audio_file_path']
audio_id = request.json['audio_id']
audio_rec = request.json['audio_rec']

on_process_audio(audio_id, audio_rec, audio_file_path)

return jsonify({"message": "Audio processing completed!"})


if __name__ == "__main__":


parser = argparse.ArgumentParser()

parser.add_argument(
"--input",
help="Path to the file to analyze",
required=True,
type=str,
)

cli_args = parser.parse_args()

on_process_audio("my-audio-id", {
"location": {
"latitude": 0,
"longitude": 0
}
}, cli_args.input)

0 comments on commit 5bf8189

Please sign in to comment.