Spaces:
Runtime error
Runtime error
Added Azure Blob Storage and AI Model Functionality to app.py
Browse files
app.py
CHANGED
|
@@ -1,8 +1,10 @@
|
|
| 1 |
import gradio as gr
|
| 2 |
import os
|
| 3 |
import subprocess
|
| 4 |
-
# install moviepy
|
| 5 |
moviepy = subprocess.run(["pip", "install", "moviepy"])
|
|
|
|
|
|
|
| 6 |
from azure.storage.blob import BlobServiceClient
|
| 7 |
import AzureBlobStorageVideo
|
| 8 |
import AzureBlobStorageAudio
|
|
@@ -39,25 +41,52 @@ def predict_video(input_video, input_audio=None, input_choice="Explosions"):
|
|
| 39 |
return [None, "Error: The upload exceeds file size 16MB. Please upload a smaller file."]
|
| 40 |
|
| 41 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 42 |
|
| 43 |
-
|
|
|
|
| 44 |
|
| 45 |
-
#
|
| 46 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 47 |
#return [input_video, f" Using uploaded audio: {input_audio.name}"]
|
| 48 |
# IF user uploads audio file: upload audio file to blob storage
|
| 49 |
# ELSE use default audio file from blob storage
|
| 50 |
|
| 51 |
|
| 52 |
# message = "**Placeholder:** Video processing not implemented yet."
|
| 53 |
-
#
|
| 54 |
-
# if input_audio is not None:
|
| 55 |
-
# AzureBlobStorageAudio.uploadUserAudioToBlobStorage(input_audio, "test8")
|
| 56 |
-
# return [input_video, message + f" Using uploaded audio: {input_audio.name}"]
|
| 57 |
-
# else:
|
| 58 |
-
# return [input_video, message + " Generated Audio will be used"]
|
| 59 |
-
|
| 60 |
-
|
| 61 |
|
| 62 |
# 2. Analyze video and predict timestamps
|
| 63 |
|
|
@@ -72,13 +101,13 @@ def predict_video(input_video, input_audio=None, input_choice="Explosions"):
|
|
| 72 |
A list containing the processed video and a message string.
|
| 73 |
"""
|
| 74 |
|
| 75 |
-
|
| 76 |
|
| 77 |
# IF method returns error: run analysis again
|
| 78 |
-
|
| 79 |
-
|
| 80 |
-
|
| 81 |
|
|
|
|
| 82 |
|
| 83 |
# 3. Use moviepy to add haptics to video
|
| 84 |
|
|
@@ -87,26 +116,27 @@ def predict_video(input_video, input_audio=None, input_choice="Explosions"):
|
|
| 87 |
#npminstall = subprocess.run(["npm", "install", "masteringModule/package.json"])
|
| 88 |
#os.chdir("..")
|
| 89 |
|
| 90 |
-
|
| 91 |
# 3.1. Extract audio from video
|
| 92 |
#extractedAudioPath = extract_audio_from_video(input_video)
|
| 93 |
|
| 94 |
# 3.2. Mix extracted audio with haptic audio
|
| 95 |
|
| 96 |
# Load JSON output
|
| 97 |
-
output_query_response = '{"value":[{"documentId":"sp=r&st=2024-02-09T12:33:24Z&se=2025-08-06T20:33:24Z&spr=https&sv=2022-11-02&sr=b&sig=V%2Fq56JjGcL60r0vt3oAPjzx%2FZMu5%2BJo%2BfjKkJF2ccgo%3D","documentKind":"VideoInterval","start":"00:00:16","end":"00:00:26","best":"00:00:21","relevance":0.4005849361419678},{"documentId":"sp=r&st=2024-02-09T12:33:24Z&se=2025-08-06T20:33:24Z&spr=https&sv=2022-11-02&sr=b&sig=V%2Fq56JjGcL60r0vt3oAPjzx%2FZMu5%2BJo%2BfjKkJF2ccgo%3D","documentKind":"VideoInterval","start":"00:00:06","end":"00:00:16","best":"00:00:09","relevance":0.38852864503860474},{"documentId":"sp=r&st=2024-02-09T12:33:24Z&se=2025-08-06T20:33:24Z&spr=https&sv=2022-11-02&sr=b&sig=V%2Fq56JjGcL60r0vt3oAPjzx%2FZMu5%2BJo%2BfjKkJF2ccgo%3D","documentKind":"VideoInterval","start":"00:01:42","end":"00:01:58","best":"00:01:43","relevance":0.38718080520629883},{"documentId":"sp=r&st=2024-02-09T12:33:24Z&se=2025-08-06T20:33:24Z&spr=https&sv=2022-11-02&sr=b&sig=V%2Fq56JjGcL60r0vt3oAPjzx%2FZMu5%2BJo%2BfjKkJF2ccgo%3D","documentKind":"VideoInterval","start":"00:01:58","end":"00:02:14","best":"00:02:03","relevance":0.3811851143836975},{"documentId":"sp=r&st=2024-02-09T12:33:24Z&se=2025-08-06T20:33:24Z&spr=https&sv=2022-11-02&sr=b&sig=V%2Fq56JjGcL60r0vt3oAPjzx%2FZMu5%2BJo%2BfjKkJF2ccgo%3D","documentKind":"VideoInterval","start":"00:00:42","end":"00:00:52","best":"00:00:42","relevance":0.3765566647052765},{"documentId":"sp=r&st=2024-02-09T12:33:24Z&se=2025-08-06T20:33:24Z&spr=https&sv=2022-11-02&sr=b&sig=V%2Fq56JjGcL60r0vt3oAPjzx%2FZMu5%2BJo%2BfjKkJF2ccgo%3D","documentKind":"VideoInterval","start":"00:00:26","end":"00:00:42","best":"00:00:28","relevance":0.3718773126602173},{"documentId":"sp=r&st=2024-02-09T12:33:24Z&se=2025-08-06T20:33:24Z&spr=https&sv=2022-11-02&sr=b&sig=V%2Fq56JjGcL60r0vt3oAPjzx%2FZMu5%2BJo%2BfjKkJF2ccgo%3D","documentKind":"VideoInterval","start":"00:01:08","end":"00:01:24","best":"00:01:10","relevance":0.3707084357738495},{"documentId":"sp=r&st=2024-02-09T12:33:24Z&se=2025-08-06T20:33:24Z&spr=https&sv=2022-11-02&sr=b&sig=V%2Fq56JjGcL60r0vt3oAPjzx%2FZMu5%2BJo%2BfjKkJF2ccgo%3D","documentKind":"VideoInterval","start":"00:01:37","end":"00:01:42","best":"00:01:38","relevance":0.36235538125038147},{"documentId":"sp=r&st=2024-02-09T12:33:24Z&se=2025-08-06T20:33:24Z&spr=https&sv=2022-11-02&sr=b&sig=V%2Fq56JjGcL60r0vt3oAPjzx%2FZMu5%2BJo%2BfjKkJF2ccgo%3D","documentKind":"VideoInterval","start":"00:01:29","end":"00:01:37","best":"00:01:33","relevance":0.3606133460998535},{"documentId":"sp=r&st=2024-02-09T12:33:24Z&se=2025-08-06T20:33:24Z&spr=https&sv=2022-11-02&sr=b&sig=V%2Fq56JjGcL60r0vt3oAPjzx%2FZMu5%2BJo%2BfjKkJF2ccgo%3D","documentKind":"VideoInterval","start":"00:01:03","end":"00:01:08","best":"00:01:04","relevance":0.3513660728931427},{"documentId":"sp=r&st=2024-02-09T12:33:24Z&se=2025-08-06T20:33:24Z&spr=https&sv=2022-11-02&sr=b&sig=V%2Fq56JjGcL60r0vt3oAPjzx%2FZMu5%2BJo%2BfjKkJF2ccgo%3D","documentKind":"VideoInterval","start":"00:00:00","end":"00:00:06","best":"00:00:05","relevance":0.3378048241138458}]}' # JSON response
|
| 98 |
|
| 99 |
|
| 100 |
-
json_data = load_json_output(
|
| 101 |
|
| 102 |
# Extract audio from the video
|
| 103 |
audio_path = extract_audio_from_video(input_video)
|
| 104 |
# Get explosion segments
|
| 105 |
explosion_segments = get_explosion_segments(json_data)
|
| 106 |
|
| 107 |
-
|
| 108 |
-
final_audio = create_final_audio(audio_path, explosion_segments)
|
| 109 |
|
|
|
|
|
|
|
|
|
|
| 110 |
# Save enhanced audio
|
| 111 |
finalAudioPath = "audio/finalAudio.mp3"
|
| 112 |
save_audio(final_audio, finalAudioPath)
|
|
@@ -115,7 +145,8 @@ def predict_video(input_video, input_audio=None, input_choice="Explosions"):
|
|
| 115 |
|
| 116 |
master = subprocess.run(["node", "masteringModule/main.js", "--input", finalAudioPath, "--output", finalAudioPath])
|
| 117 |
|
| 118 |
-
|
|
|
|
| 119 |
|
| 120 |
# Extract video without audio
|
| 121 |
current_video = without_audio(VideoFileClip(input_video))
|
|
|
|
| 1 |
import gradio as gr
|
| 2 |
import os
|
| 3 |
import subprocess
|
| 4 |
+
# install moviepy dependency
|
| 5 |
moviepy = subprocess.run(["pip", "install", "moviepy"])
|
| 6 |
+
ffmpeg = subprocess.run(["pip", "install", "ffmpeg-python"])
|
| 7 |
+
pipUpdate = subprocess.run(["pip", "install", "--upgrade", "pip"])
|
| 8 |
from azure.storage.blob import BlobServiceClient
|
| 9 |
import AzureBlobStorageVideo
|
| 10 |
import AzureBlobStorageAudio
|
|
|
|
| 41 |
return [None, "Error: The upload exceeds file size 16MB. Please upload a smaller file."]
|
| 42 |
|
| 43 |
|
| 44 |
+
#Initialize blob storage credentials
|
| 45 |
+
storage_account_name = "useruploadhuggingface"
|
| 46 |
+
storage_account_key = "zhrGpPBX6PVD+krncC4nVF4yoweEku/z2ErVxjLiuu/CjAVKqM5O4xlGWEyuWGxptL3mA1pv/6P4+AStjSjLEQ=="
|
| 47 |
+
connection_string = f"DefaultEndpointsProtocol=https;AccountName={storage_account_name};AccountKey={storage_account_key};EndpointSuffix=core.windows.net"
|
| 48 |
|
| 49 |
+
video_container_name = "useruploadhuggingfacevideo"
|
| 50 |
+
audio_container_name = "useruploadhuggingfaceaudio"
|
| 51 |
|
| 52 |
+
# 1. Upload user video file to azure blob storage
|
| 53 |
|
| 54 |
+
videoBlobURL = AzureBlobStorageVideo.uploadUserVideoToBlobStorage(input_video, filename)
|
| 55 |
+
videoSASToken = AzureBlobStorageVideo.generateSASToken(storage_account_name,video_container_name, filename, storage_account_key)
|
| 56 |
+
videoSASURL = AzureBlobStorageVideo.generateSASURL(storage_account_name, video_container_name, filename, videoSASToken)
|
| 57 |
+
|
| 58 |
+
# 1.1. Upload user audio if available
|
| 59 |
+
|
| 60 |
+
userAudioInputFlag = False
|
| 61 |
+
|
| 62 |
+
if input_audio is not None:
|
| 63 |
+
audioFileName = "userInputAudio"
|
| 64 |
+
input_audio = AzureBlobStorageAudio.uploadUserAudioToBlobStorage(input_audio, audioFileName)
|
| 65 |
+
userAudioInputFlag = True
|
| 66 |
+
#return [input_video, f" Using uploaded audio: {audioFileName}"]
|
| 67 |
+
else:
|
| 68 |
+
if (input_choice == "Explosions"):
|
| 69 |
+
input_audio = "https://audiolibrary.blob.core.windows.net/audiolibrary/1_seconds_haptic_audio.mp3"
|
| 70 |
+
print("explosion selected")
|
| 71 |
+
elif (input_choice == "Lightning and Thunder"):
|
| 72 |
+
input_audio = "https://audiolibrary.blob.core.windows.net/audiolibrary/8_seconds_Thunder.mp3"
|
| 73 |
+
print("lightning and thunder selected")
|
| 74 |
+
elif (input_choice == "Vehicle Racing"):
|
| 75 |
+
input_audio = "https://audiolibrary.blob.core.windows.net/audiolibrary/5_seconds_vehicle_audio.mp3"
|
| 76 |
+
print("vehicle racing selected")
|
| 77 |
+
else:
|
| 78 |
+
input_audio = "https://audiolibrary.blob.core.windows.net/audiolibrary/5_seconds_haptic_videos.mp3"
|
| 79 |
+
print("default selected")
|
| 80 |
+
|
| 81 |
+
#return [input_video, f" {choice}"]
|
| 82 |
+
|
| 83 |
+
#return [videoBlobURL, f" Using uploaded audio:"]
|
| 84 |
#return [input_video, f" Using uploaded audio: {input_audio.name}"]
|
| 85 |
# IF user uploads audio file: upload audio file to blob storage
|
| 86 |
# ELSE use default audio file from blob storage
|
| 87 |
|
| 88 |
|
| 89 |
# message = "**Placeholder:** Video processing not implemented yet."
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 90 |
|
| 91 |
# 2. Analyze video and predict timestamps
|
| 92 |
|
|
|
|
| 101 |
A list containing the processed video and a message string.
|
| 102 |
"""
|
| 103 |
|
| 104 |
+
responseQueryText = videoAnalysis(videoSASURL, videoSASToken, input_choice)
|
| 105 |
|
| 106 |
# IF method returns error: run analysis again
|
| 107 |
+
if responseQueryText == """{"error":{"code":"InvalidRequest","message":"Value for indexName is invalid."}}""":
|
| 108 |
+
responseQueryText = videoAnalysis(videoSASURL, videoSASToken, input_choice)
|
|
|
|
| 109 |
|
| 110 |
+
AzureBlobStorageVideo.deleteUserVideoFromBlobStorage(video_container_name,filename)
|
| 111 |
|
| 112 |
# 3. Use moviepy to add haptics to video
|
| 113 |
|
|
|
|
| 116 |
#npminstall = subprocess.run(["npm", "install", "masteringModule/package.json"])
|
| 117 |
#os.chdir("..")
|
| 118 |
|
|
|
|
| 119 |
# 3.1. Extract audio from video
|
| 120 |
#extractedAudioPath = extract_audio_from_video(input_video)
|
| 121 |
|
| 122 |
# 3.2. Mix extracted audio with haptic audio
|
| 123 |
|
| 124 |
# Load JSON output
|
| 125 |
+
#output_query_response = '{"value":[{"documentId":"sp=r&st=2024-02-09T12:33:24Z&se=2025-08-06T20:33:24Z&spr=https&sv=2022-11-02&sr=b&sig=V%2Fq56JjGcL60r0vt3oAPjzx%2FZMu5%2BJo%2BfjKkJF2ccgo%3D","documentKind":"VideoInterval","start":"00:00:16","end":"00:00:26","best":"00:00:21","relevance":0.4005849361419678},{"documentId":"sp=r&st=2024-02-09T12:33:24Z&se=2025-08-06T20:33:24Z&spr=https&sv=2022-11-02&sr=b&sig=V%2Fq56JjGcL60r0vt3oAPjzx%2FZMu5%2BJo%2BfjKkJF2ccgo%3D","documentKind":"VideoInterval","start":"00:00:06","end":"00:00:16","best":"00:00:09","relevance":0.38852864503860474},{"documentId":"sp=r&st=2024-02-09T12:33:24Z&se=2025-08-06T20:33:24Z&spr=https&sv=2022-11-02&sr=b&sig=V%2Fq56JjGcL60r0vt3oAPjzx%2FZMu5%2BJo%2BfjKkJF2ccgo%3D","documentKind":"VideoInterval","start":"00:01:42","end":"00:01:58","best":"00:01:43","relevance":0.38718080520629883},{"documentId":"sp=r&st=2024-02-09T12:33:24Z&se=2025-08-06T20:33:24Z&spr=https&sv=2022-11-02&sr=b&sig=V%2Fq56JjGcL60r0vt3oAPjzx%2FZMu5%2BJo%2BfjKkJF2ccgo%3D","documentKind":"VideoInterval","start":"00:01:58","end":"00:02:14","best":"00:02:03","relevance":0.3811851143836975},{"documentId":"sp=r&st=2024-02-09T12:33:24Z&se=2025-08-06T20:33:24Z&spr=https&sv=2022-11-02&sr=b&sig=V%2Fq56JjGcL60r0vt3oAPjzx%2FZMu5%2BJo%2BfjKkJF2ccgo%3D","documentKind":"VideoInterval","start":"00:00:42","end":"00:00:52","best":"00:00:42","relevance":0.3765566647052765},{"documentId":"sp=r&st=2024-02-09T12:33:24Z&se=2025-08-06T20:33:24Z&spr=https&sv=2022-11-02&sr=b&sig=V%2Fq56JjGcL60r0vt3oAPjzx%2FZMu5%2BJo%2BfjKkJF2ccgo%3D","documentKind":"VideoInterval","start":"00:00:26","end":"00:00:42","best":"00:00:28","relevance":0.3718773126602173},{"documentId":"sp=r&st=2024-02-09T12:33:24Z&se=2025-08-06T20:33:24Z&spr=https&sv=2022-11-02&sr=b&sig=V%2Fq56JjGcL60r0vt3oAPjzx%2FZMu5%2BJo%2BfjKkJF2ccgo%3D","documentKind":"VideoInterval","start":"00:01:08","end":"00:01:24","best":"00:01:10","relevance":0.3707084357738495},{"documentId":"sp=r&st=2024-02-09T12:33:24Z&se=2025-08-06T20:33:24Z&spr=https&sv=2022-11-02&sr=b&sig=V%2Fq56JjGcL60r0vt3oAPjzx%2FZMu5%2BJo%2BfjKkJF2ccgo%3D","documentKind":"VideoInterval","start":"00:01:37","end":"00:01:42","best":"00:01:38","relevance":0.36235538125038147},{"documentId":"sp=r&st=2024-02-09T12:33:24Z&se=2025-08-06T20:33:24Z&spr=https&sv=2022-11-02&sr=b&sig=V%2Fq56JjGcL60r0vt3oAPjzx%2FZMu5%2BJo%2BfjKkJF2ccgo%3D","documentKind":"VideoInterval","start":"00:01:29","end":"00:01:37","best":"00:01:33","relevance":0.3606133460998535},{"documentId":"sp=r&st=2024-02-09T12:33:24Z&se=2025-08-06T20:33:24Z&spr=https&sv=2022-11-02&sr=b&sig=V%2Fq56JjGcL60r0vt3oAPjzx%2FZMu5%2BJo%2BfjKkJF2ccgo%3D","documentKind":"VideoInterval","start":"00:01:03","end":"00:01:08","best":"00:01:04","relevance":0.3513660728931427},{"documentId":"sp=r&st=2024-02-09T12:33:24Z&se=2025-08-06T20:33:24Z&spr=https&sv=2022-11-02&sr=b&sig=V%2Fq56JjGcL60r0vt3oAPjzx%2FZMu5%2BJo%2BfjKkJF2ccgo%3D","documentKind":"VideoInterval","start":"00:00:00","end":"00:00:06","best":"00:00:05","relevance":0.3378048241138458}]}' # JSON response
|
| 126 |
|
| 127 |
|
| 128 |
+
json_data = load_json_output(responseQueryText)
|
| 129 |
|
| 130 |
# Extract audio from the video
|
| 131 |
audio_path = extract_audio_from_video(input_video)
|
| 132 |
# Get explosion segments
|
| 133 |
explosion_segments = get_explosion_segments(json_data)
|
| 134 |
|
| 135 |
+
print(input_audio)
|
|
|
|
| 136 |
|
| 137 |
+
# Create final audio
|
| 138 |
+
#final_audio = create_final_audio(audio_path, explosion_segments)
|
| 139 |
+
final_audio = create_final_audio(audio_path, input_audio, explosion_segments)
|
| 140 |
# Save enhanced audio
|
| 141 |
finalAudioPath = "audio/finalAudio.mp3"
|
| 142 |
save_audio(final_audio, finalAudioPath)
|
|
|
|
| 145 |
|
| 146 |
master = subprocess.run(["node", "masteringModule/main.js", "--input", finalAudioPath, "--output", finalAudioPath])
|
| 147 |
|
| 148 |
+
if (userAudioInputFlag == True):
|
| 149 |
+
AzureBlobStorageAudio.deleteUserAudioFromBlobStorage(audio_container_name, audioFileName)
|
| 150 |
|
| 151 |
# Extract video without audio
|
| 152 |
current_video = without_audio(VideoFileClip(input_video))
|