Create requirements.txt

#30
by Banuka - opened
AzureBlobStorageAudio.py CHANGED
@@ -7,34 +7,23 @@ storage_account_key = "zhrGpPBX6PVD+krncC4nVF4yoweEku/z2ErVxjLiuu/CjAVKqM5O4xlGW
7
  connection_string = f"DefaultEndpointsProtocol=https;AccountName={storage_account_name};AccountKey={storage_account_key};EndpointSuffix=core.windows.net"
8
 
9
  container_name = "useruploadhuggingfaceaudio" # Update container name for audio files
10
- #file_path = r"C:\Users\ASUS\Desktop\UoW\2ND YEAR\SDGP\AUDIO\edit\3_second_audio.flac" # Update path to your MP3 file
11
- #file_name = "uploaded_audio.mp3"
12
 
13
 
14
- def delete_container(container_id: str) -> None:
15
- """
16
- Deletes all blobs within a specified Azure Blob Storage container.
17
-
18
- Args:
19
- container_id (str): The ID of the container to delete.
20
- """
21
- try:
22
- # Establish connection using your storage connection string (replace with yours)
23
- storage_connection_string = 'DefaultEndpointsProtocol=https;AccountName=useruploadhuggingface;AccountKey=zhrGpPBX6PVD+krncC4nVF4yoweEku/z2ErVxjLiuu/CjAVKqM5O4xlGWEyuWGxptL3mA1pv/6P4+AStjSjLEQ==;EndpointSuffix=core.windows.net'
24
- blob_service_client = azure.storage.blob.BlobServiceClient.from_connection_string(storage_connection_string)
25
-
26
- # Get container client
27
- container_client = blob_service_client.get_container_client(container_id)
28
-
29
- # Delete all blobs in the container (iterator for large datasets)
30
- blobs = container_client.list_blobs()
31
- for blob in blobs:
32
- container_client.delete_blob(blob.name)
33
- print(f'Container "{container_id}" emptied successfully.')
34
-
35
- except Exception as e:
36
- print(f'Error deleting blobs: {e}')
37
 
 
 
 
 
 
 
 
 
 
 
38
 
39
  def uploadUserAudioToBlobStorage(file_path, file_name):
40
  """Uploads an MP3 audio file to the specified Azure Blob Storage container and returns the URL.
@@ -88,4 +77,4 @@ if __name__ == "__main__":
88
  container_client = blob_service_client.get_container_client(container_name)
89
 
90
  # Pass container_client and file_name to the deletion function
91
- delete_container('useruploadhuggingfaceaudio')
 
7
  connection_string = f"DefaultEndpointsProtocol=https;AccountName={storage_account_name};AccountKey={storage_account_key};EndpointSuffix=core.windows.net"
8
 
9
  container_name = "useruploadhuggingfaceaudio" # Update container name for audio files
10
+ file_path = r"C:\Users\ASUS\Desktop\UoW\2ND YEAR\SDGP\AUDIO\edit\3_second_audio.flac" # Update path to your MP3 file
11
+ file_name = "uploaded_audio.mp3"
12
 
13
 
14
+ def deleteUserAudioFromBlobStorage(container_client,blob_name):
15
+ """Deletes the specified blob from Azure Blob Storage.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
16
 
17
+ Args:
18
+ blob_client (BlobClient): The BlobClient object for the blob to delete.
19
+ """
20
+ try:
21
+ # Get the blob client within the function for deletion
22
+ blob_client = container_client.get_blob_client(blob_name)
23
+ blob_client.delete_blob()
24
+ print(f"Audio deleted successfully from Azure Blob Storage.")
25
+ except Exception as e:
26
+ print(f"Error deleting audio: {e}")
27
 
28
  def uploadUserAudioToBlobStorage(file_path, file_name):
29
  """Uploads an MP3 audio file to the specified Azure Blob Storage container and returns the URL.
 
77
  container_client = blob_service_client.get_container_client(container_name)
78
 
79
  # Pass container_client and file_name to the deletion function
80
+ deleteUserAudioFromBlobStorage(container_client, file_name)
AzureBlobStorageVideo.py CHANGED
@@ -1,43 +1,28 @@
1
- import azure.storage.blob # Import required library
2
- from azure.storage.blob import BlobServiceClient, generate_blob_sas, BlobSasPermissions
3
- from datetime import datetime, timedelta
4
 
5
  # Parameters for linking Azure to the application
6
  storage_account_key = "zhrGpPBX6PVD+krncC4nVF4yoweEku/z2ErVxjLiuu/CjAVKqM5O4xlGWEyuWGxptL3mA1pv/6P4+AStjSjLEQ=="
7
  storage_account_name = "useruploadhuggingface"
8
  connection_string = f"DefaultEndpointsProtocol=https;AccountName={storage_account_name};AccountKey={storage_account_key};EndpointSuffix=core.windows.net"
9
  container_name = "useruploadhuggingfacevideo"
10
- #file_path = r"C:\Users\isuru\Documents\IIT University\Modules\Year 2 - Semester 2\SDGP\HapticAudio SE09 Local Repo\gradio-env\HapticsProject\video\WIND ANIMATION.mp4"
11
- #file_name = "wind_video.mp4"
12
- target_container_id = 'useruploadhuggingfacevideo'
13
 
14
 
15
 
16
- def delete_container(container_id: str) -> None:
17
- """
18
- Deletes all blobs within a specified Azure Blob Storage container.
19
-
20
- Args:
21
- container_id (str): The ID of the container to delete.
22
- """
23
- try:
24
- # Establish connection using your storage connection string (replace with yours)
25
- storage_connection_string = 'DefaultEndpointsProtocol=https;AccountName=useruploadhuggingface;AccountKey=zhrGpPBX6PVD+krncC4nVF4yoweEku/z2ErVxjLiuu/CjAVKqM5O4xlGWEyuWGxptL3mA1pv/6P4+AStjSjLEQ==;EndpointSuffix=core.windows.net'
26
- blob_service_client = azure.storage.blob.BlobServiceClient.from_connection_string(storage_connection_string)
27
-
28
- # Get container client
29
- container_client = blob_service_client.get_container_client(container_id)
30
-
31
- # Delete all blobs in the container (iterator for large datasets)
32
- blobs = container_client.list_blobs()
33
- for blob in blobs:
34
- container_client.delete_blob(blob.name)
35
- print(f'Container "{container_id}" emptied successfully.')
36
-
37
- except Exception as e:
38
- print(f'Error deleting blobs: {e}')
39
-
40
 
 
 
 
 
 
 
 
 
 
 
41
 
42
 
43
  def uploadUserVideoToBlobStorage(file_path, file_name):
@@ -79,27 +64,6 @@ def uploadUserVideoToBlobStorage(file_path, file_name):
79
  print(f"Error: File not found at {file_path}.")
80
  raise # Re-raise the exception for further handling
81
 
82
-
83
- def generateSASToken(account_name,container_name, blob_name, account_key):
84
- sas_token = generate_blob_sas(account_name=account_name,
85
- container_name=container_name,
86
- blob_name=blob_name,
87
- account_key=account_key,
88
- permission=BlobSasPermissions(read=True),
89
- expiry=datetime.utcnow() + timedelta(hours=1))
90
-
91
- print(f"SAS Token generated:{sas_token}")
92
-
93
- return sas_token
94
-
95
-
96
- def generateSASURL(account_name, container_name, blob_name, sas_token):
97
-
98
- sas_url = 'https://' + account_name + '.blob.core.windows.net/' + container_name + '/' + blob_name + '?' + sas_token
99
- print(f"SAS URL Generated: {sas_url}")
100
-
101
- return sas_url
102
-
103
  if __name__ == "__main__":
104
  # Example usage
105
  uploaded_video_url = uploadUserVideoToBlobStorage(file_path, file_name)
@@ -107,5 +71,9 @@ if __name__ == "__main__":
107
  # Retrieve container_client from within the upload function
108
  blob_service_client = BlobServiceClient.from_connection_string(conn_str=connection_string)
109
  container_client = blob_service_client.get_container_client(container_name)
110
- target_container_id = 'useruploadhuggingfacevideo'
111
- deleteUserVideoFromBlobStorage(target_container_id)
 
 
 
 
 
1
+ from azure.storage.blob import BlobServiceClient
 
 
2
 
3
  # Parameters for linking Azure to the application
4
  storage_account_key = "zhrGpPBX6PVD+krncC4nVF4yoweEku/z2ErVxjLiuu/CjAVKqM5O4xlGWEyuWGxptL3mA1pv/6P4+AStjSjLEQ=="
5
  storage_account_name = "useruploadhuggingface"
6
  connection_string = f"DefaultEndpointsProtocol=https;AccountName={storage_account_name};AccountKey={storage_account_key};EndpointSuffix=core.windows.net"
7
  container_name = "useruploadhuggingfacevideo"
8
+ file_path = r"C:\Users\ASUS\Desktop\UoW\2ND YEAR\SDGP\HuggingFace\Video\production_id_5091624 (1080p).mp4"
9
+ file_name = "uploaded_video.mp4"
 
10
 
11
 
12
 
13
+ def deleteUserVideoFromBlobStorage(container_client,blob_name):
14
+ """Deletes the specified blob from Azure Blob Storage.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15
 
16
+ Args:
17
+ blob_client (BlobClient): The BlobClient object for the blob to delete.
18
+ """
19
+ try:
20
+ # Get the blob client within the function for deletion
21
+ blob_client = container_client.get_blob_client(blob_name)
22
+ blob_client.delete_blob()
23
+ print(f"Video deleted successfully from Azure Blob Storage.")
24
+ except Exception as e:
25
+ print(f"Error deleting video: {e}")
26
 
27
 
28
  def uploadUserVideoToBlobStorage(file_path, file_name):
 
64
  print(f"Error: File not found at {file_path}.")
65
  raise # Re-raise the exception for further handling
66
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
67
  if __name__ == "__main__":
68
  # Example usage
69
  uploaded_video_url = uploadUserVideoToBlobStorage(file_path, file_name)
 
71
  # Retrieve container_client from within the upload function
72
  blob_service_client = BlobServiceClient.from_connection_string(conn_str=connection_string)
73
  container_client = blob_service_client.get_container_client(container_name)
74
+
75
+ # Pass container_client and file_name to the deletion function
76
+ deleteUserVideoFromBlobStorage(container_client,file_name)
77
+
78
+
79
+
Moviepy ADDED
@@ -0,0 +1,106 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from moviepy.editor import *
2
+ import json
3
+
4
+
5
+ current_video_path = r"C:\Users\ASUS\Desktop\UoW\2ND YEAR\SDGP\Test Video\test_video.mp4"
6
+ current_video = VideoFileClip(current_video_path) # location of the uploaded video
7
+ 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
8
+
9
+
10
+ # Convert JSON string to Python dictionary
11
+ data = json.loads(output_query_response)
12
+
13
+
14
+ # creating an empty array for the results
15
+ result = []
16
+
17
+
18
+ # iterate over every explosion occurrence and find start, end, best values using the ml algorithm
19
+ for i in data["value"]:
20
+ result.append([i["start"], i["end"], i["best"]])
21
+
22
+
23
+ # update start_explosion_time and end_explosion_time for each explosion occurrence
24
+ for explosion in result:
25
+ best_time = explosion[2]
26
+ best_time_seconds = sum(x * int(t) for x, t in zip([3600, 60, 1], best_time.split(":")))
27
+ start_explosion_time_seconds = best_time_seconds - 1
28
+ end_explosion_time_seconds = best_time_seconds + 2
29
+ explosion[0] = "{:02d}:{:02d}:{:02d}".format(start_explosion_time_seconds // 3600,
30
+ (start_explosion_time_seconds % 3600 // 60),
31
+ start_explosion_time_seconds % 60)
32
+ explosion[1] = "{:02d}:{:02d}:{:02d}".format(end_explosion_time_seconds // 3600,
33
+ (end_explosion_time_seconds % 3600 // 60),
34
+ end_explosion_time_seconds % 60)
35
+
36
+
37
+ # Extracting audio from the video
38
+ current_audio_path = "current_audio.mp3"
39
+ if current_video.audio is not None:
40
+ current_video.audio.write_audiofile(current_audio_path) # location of the audio clip
41
+ print("Audio file has been extracted from the video")
42
+ else:
43
+ print("No audio found in the video.")
44
+
45
+
46
+ # Loading the whole audio clip from the uploaded video
47
+ current_audio = AudioFileClip(current_audio_path)
48
+
49
+
50
+ # define the segments for the audio clips
51
+ final_audio_segments = []
52
+ haptic_audio_path = 'https://phonebrrdemonstration2.blob.core.windows.net/audio3secondsmp3/3_second_explosion_00001.mp3'
53
+ haptic_audio = AudioFileClip(haptic_audio_path)
54
+
55
+
56
+ # Iterate through each explosion occurrence and create audio segments
57
+ for explosion in result:
58
+ start_explosion_time = sum(x * int(t) for x, t in zip([3600, 60, 1], explosion[0].split(":")))
59
+ end_explosion_time = sum(x * int(t) for x, t in zip([3600, 60, 1], explosion[1].split(":")))
60
+
61
+ beginning_audio_clip = current_audio.subclip(0, start_explosion_time)
62
+ end_audio_clip = current_audio.subclip(end_explosion_time)
63
+
64
+ # Adjust the duration of the haptic audio to match the duration between start and end explosion times
65
+ haptic_audio_duration = end_explosion_time - start_explosion_time
66
+ haptic_audio_clip = haptic_audio.subclip(0, haptic_audio_duration)
67
+
68
+ final_audio = concatenate_audioclips([beginning_audio_clip, haptic_audio_clip, end_audio_clip])
69
+ final_audio_segments.append(final_audio)
70
+
71
+
72
+ # concatenate final audio segments
73
+ final_audio = concatenate_audioclips(final_audio_segments)
74
+
75
+
76
+ # Match the audio duration with the video duration
77
+ final_audio = final_audio.set_duration(current_video.duration)
78
+
79
+
80
+ # Save the enhanced audio
81
+ final_audio_path = "output.mp3"
82
+ final_audio.write_audiofile(final_audio_path)
83
+ print("Enhanced audio has been created")
84
+
85
+
86
+ # create a video without audio
87
+ extracted_video = current_video.without_audio()
88
+
89
+
90
+ # save the video without audio
91
+ extracted_video_path = "output.mp4"
92
+ extracted_video.write_videofile(extracted_video_path, fps=60)
93
+ print("Video without audio has been created")
94
+
95
+
96
+ # combine the final video without the enhanced audio
97
+ final_video = extracted_video.set_audio(final_audio)
98
+
99
+
100
+ # save the final video
101
+ final_video_path = "final_video.mp4"
102
+ final_video.write_videofile(final_video_path)
103
+ print("Final video has been created")
104
+
105
+
106
+
Moviepy.py DELETED
@@ -1,107 +0,0 @@
1
- from moviepy.editor import *
2
- import json
3
-
4
- def load_json_output(output_query_response):
5
- # Convert JSON string to Python dictionary
6
- return json.loads(output_query_response)
7
-
8
- def extract_audio_from_video(video_path):
9
- video = VideoFileClip(video_path)
10
- audio_path = "audio/current_audio.mp3"
11
- if video.audio is not None:
12
- video.audio.write_audiofile(audio_path)
13
- print("Audio file has been extracted from the video")
14
- return audio_path
15
- else:
16
- print("No audio found in the video.")
17
- return None
18
-
19
- def get_explosion_segments(json_data):
20
- # creating an empty array for the results
21
- result = []
22
- # iterate over every explosion occurrence and find start, end, best values using the ml algorithm
23
- for i in json_data["value"]:
24
- result.append([i["start"], i["end"], i["best"]])
25
-
26
- # update start_explosion_time and end_explosion_time for each explosion occurrence
27
- for explosion in result:
28
- best_time = explosion[2]
29
- best_time_seconds = sum(x * int(t) for x, t in zip([3600, 60, 1], best_time.split(":")))
30
- start_explosion_time_seconds = best_time_seconds - 2
31
- end_explosion_time_seconds = best_time_seconds + 1
32
- explosion[0] = "{:02d}:{:02d}:{:02d}".format(start_explosion_time_seconds // 3600,
33
- (start_explosion_time_seconds % 3600 // 60),
34
- start_explosion_time_seconds % 60)
35
- explosion[1] = "{:02d}:{:02d}:{:02d}".format(end_explosion_time_seconds // 3600,
36
- (end_explosion_time_seconds % 3600 // 60),
37
- end_explosion_time_seconds % 60)
38
- return result
39
-
40
- def create_final_audio(current_audio_path, haptic_audio_path, explosion_segments):
41
- current_audio = AudioFileClip(current_audio_path) # location of the uploaded video
42
- # define the segments for the audio clips
43
- final_audio_segments = []
44
- #haptic_audio_path = haptic_audio_url
45
- haptic_audio = AudioFileClip(haptic_audio_path)
46
-
47
- # Iterate through each explosion occurrence and create audio segments
48
- for explosion in explosion_segments:
49
- best_explosion_time = explosion[2]
50
- best_explosion_time_seconds = sum(x * int(t) for x, t in zip([3600, 60, 1], best_explosion_time.split(":")))
51
-
52
- # Adjust the duration of the haptic audio to match the duration of the explosion
53
- haptic_audio_duration = haptic_audio.duration
54
- haptic_audio_clip = haptic_audio.subclip(0, haptic_audio_duration)
55
-
56
- # Create an audio clip starting from the best explosion time
57
- explosion_audio_clip = current_audio.subclip(best_explosion_time_seconds - 1,
58
- best_explosion_time_seconds + haptic_audio_duration)
59
-
60
- # Concatenate the haptic audio clip with the explosion audio clip
61
- final_audio = concatenate_audioclips([explosion_audio_clip, haptic_audio_clip])
62
- final_audio_segments.append(final_audio)
63
-
64
- # concatenate final audio segments
65
- final_audio = concatenate_audioclips(final_audio_segments)
66
- # Match the audio duration with the video duration
67
- final_audio = final_audio.set_duration(current_audio.duration)
68
- return final_audio
69
-
70
- def master_audio(audio_clip):
71
- # Apply audio mastering techniques here
72
- # Example: loudness normalization, equalization, compression, etc.
73
- # Replace the following line with your audio mastering process
74
- mastered_audio = audio_clip.fx(afx.audio_normalize)
75
- return mastered_audio
76
-
77
- def save_audio(audio_clip, file_path):
78
- audio_clip.write_audiofile(file_path)
79
- print("Enhanced audio has been created")
80
-
81
- def without_audio(video_clip):
82
- return video_clip.without_audio()
83
-
84
- def combine_video_audio(video_clip, audio_clip):
85
- return video_clip.set_audio(audio_clip)
86
-
87
- def save_video(video_clip, file_path):
88
- video_clip.write_videofile(file_path, fps=60)
89
- print("Final video has been created")
90
-
91
- def process_video(current_video_path, output_query_response):
92
- json_data = load_json_output(output_query_response)
93
- audio_path = extract_audio_from_video(current_video_path)
94
- if audio_path:
95
- explosion_segments = get_explosion_segments(json_data)
96
- final_audio = create_final_audio(audio_path, explosion_segments)
97
- final_audio_mastered = master_audio(final_audio)
98
- save_audio(final_audio_mastered, "output.mp3")
99
-
100
- current_video = VideoFileClip(current_video_path)# Extracting audio from the video
101
- extracted_video = without_audio(current_video)
102
-
103
- final_video = combine_video_audio(extracted_video, final_audio_mastered)
104
- save_video(final_video, "final_video.mp4")
105
-
106
-
107
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
README.md CHANGED
@@ -11,60 +11,3 @@ license: unknown
11
  ---
12
 
13
  Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
14
-
15
- # Phone Brr
16
-
17
- This project empowers you to create engaging videos with haptic feedback seamlessly integrated. Leverage the power of Azure Video Analysis and Summary, MoviePy for video processing, and Gradio for an intuitive web user interface.
18
-
19
- Link to the Hugging Face Space: https://huggingface.co/spaces/SE-09/HapticsProject
20
-
21
- ## Features
22
-
23
- - **AI-powered Haptic Integration:** Intelligently identify video segments that benefit from haptic effects using Azure Video Analysis and Summary.
24
- - **Effortless Video Editing:** Utilize MoviePy's capabilities for efficient video processing and precise editing.
25
- - **Curated Haptic Library:** Store and manage haptic audio clips in Azure Blob Storage for flexible incorporation into your videos.
26
- - **Web-based Interface:** Gradio provides a user-friendly web UI where you can effortlessly upload videos, select haptic audio clips, and generate the final enhanced video.
27
- - **Audio Mastering:** Add a final touch of polish with AI-powered audio mastering to ensure a well-balanced and professional sound.
28
-
29
-
30
- ## Installation
31
-
32
- **Prerequsites:** Ensure you have Python 3.8 or higher installed along with the required libraries:
33
- - ` azure-cognitiveservices-videoanalyzer `
34
- - ` moviepy `
35
- - ` gradio `
36
- - ` requests `
37
- - ` pydub `
38
- - ` ffmprg `
39
- - ` subprocess `
40
- - You can install them using
41
- ```bash
42
- pip install azure-cognitiveservices-videoanalyzer moviepy gradio requests pydub ffmprg subprocess
43
- ```
44
-
45
- ## Usage
46
-
47
- 1. **Clone the Repository:**
48
- - Use `git clone https://huggingface.co/spaces/SE-09/HapticsProject` to clone the Repository locally.
49
- 2. **Configuration:**
50
- - Set up a gradio virtual environment following [these steps](https://www.gradio.app/guides/installing-gradio-in-a-virtual-environment) before installing gradio.
51
- - Install the remianing python libraries and dependancies.
52
- 3. **Video Editing and Haptic Audio Integration:**
53
- - Upload a Video file using the web interface.
54
- - Additional optional Input fields to upload a custom Audio track along with specifying the instance to add haptics to.
55
- - Click "Submit" button.
56
- 4. **Output:**
57
- - Upon sucessful processing the output fields will preview a video that can be downloaded.
58
-
59
-
60
-
61
- ## Authors
62
-
63
- - [@Hussain](https://github.com/HussainLatiff)
64
- - [@Ravija](https://github.com/ravijaanthony)
65
- - [@Shashika](https://github.com/Shashika-bit)
66
- - [@Banuka](https://github.com/BanukaMandinu)
67
- - [@Isuru](https://github.com/isururana)
68
-
69
-
70
-
 
11
  ---
12
 
13
  Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
apiTest.py CHANGED
@@ -136,9 +136,17 @@ sas_url_1= "https://store1video.blob.core.windows.net/haptic-vid/test_video.mp4?
136
  #query of what you are looking for
137
  instance_1 = "Explosion"
138
 
 
 
 
 
139
  #Enter the sas token
140
  sas_token_2 = "sp=r&st=2024-03-18T09:48:32Z&se=2026-07-02T17:48:32Z&spr=https&sv=2022-11-02&sr=b&sig=hLiFrDUtrutW9FWWRR7Z0Kbc4wkHs28YR9RXjVxw8uc%3D"
141
  #the sas url
142
  sas_url_2= "https://store1video.blob.core.windows.net/haptic-vid/desert_vehicle_test.mp4?sp=r&st=2024-03-18T09:48:32Z&se=2026-07-02T17:48:32Z&spr=https&sv=2022-11-02&sr=b&sig=hLiFrDUtrutW9FWWRR7Z0Kbc4wkHs28YR9RXjVxw8uc%3D"
143
  #query of what you are looking for
144
  instance_2 = "Vehicle racing"
 
 
 
 
 
136
  #query of what you are looking for
137
  instance_1 = "Explosion"
138
 
139
+ #calling the method returns the nested list of the time frames
140
+ #test_explosion = videoAnalysis(sas_token_1, sas_url_1, instance_1)
141
+ #print(test_explosion)
142
+
143
  #Enter the sas token
144
  sas_token_2 = "sp=r&st=2024-03-18T09:48:32Z&se=2026-07-02T17:48:32Z&spr=https&sv=2022-11-02&sr=b&sig=hLiFrDUtrutW9FWWRR7Z0Kbc4wkHs28YR9RXjVxw8uc%3D"
145
  #the sas url
146
  sas_url_2= "https://store1video.blob.core.windows.net/haptic-vid/desert_vehicle_test.mp4?sp=r&st=2024-03-18T09:48:32Z&se=2026-07-02T17:48:32Z&spr=https&sv=2022-11-02&sr=b&sig=hLiFrDUtrutW9FWWRR7Z0Kbc4wkHs28YR9RXjVxw8uc%3D"
147
  #query of what you are looking for
148
  instance_2 = "Vehicle racing"
149
+
150
+ #calling the method returns the nested list of the time frames
151
+ #test_vehicle = videoAnalysis(sas_token_2, sas_url_2, instance_2)
152
+ #print(test_vehicle)
app.py CHANGED
@@ -1,26 +1,11 @@
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
11
- from apiTest import videoAnalysis
12
- from Moviepy import extract_audio_from_video
13
- from Moviepy import load_json_output
14
- from Moviepy import get_explosion_segments
15
- from Moviepy import create_final_audio
16
- from Moviepy import save_audio
17
- from Moviepy import without_audio
18
- from Moviepy import combine_video_audio
19
- from Moviepy import save_video
20
- from moviepy.editor import *
21
- import json
22
-
23
- def predict_video(input_video, input_audio=None, input_choice="Explosions"):
24
  global filename, file_size # Use the global keyword to refer to the global variables
25
 
26
  # Check if the video is available
@@ -36,42 +21,10 @@ def predict_video(input_video, input_audio=None, input_choice="Explosions"):
36
 
37
  if file_size > 20 * 1024 * 1024:
38
  return [None, "Error: The upload exceeds file size 16MB. Please upload a smaller file."]
39
-
40
-
41
- #Initialize blob storage credentials
42
- storage_account_name = "useruploadhuggingface"
43
- storage_account_key = "zhrGpPBX6PVD+krncC4nVF4yoweEku/z2ErVxjLiuu/CjAVKqM5O4xlGWEyuWGxptL3mA1pv/6P4+AStjSjLEQ=="
44
- connection_string = f"DefaultEndpointsProtocol=https;AccountName={storage_account_name};AccountKey={storage_account_key};EndpointSuffix=core.windows.net"
45
-
46
- video_container_name = "useruploadhuggingfacevideo"
47
- audio_container_name = "useruploadhuggingfaceaudio"
48
-
49
- # 1. Upload user video file to azure blob storage
50
-
51
- videoBlobURL = AzureBlobStorageVideo.uploadUserVideoToBlobStorage(input_video, filename)
52
- videoSASToken = AzureBlobStorageVideo.generateSASToken(storage_account_name,video_container_name, filename, storage_account_key)
53
- videoSASURL = AzureBlobStorageVideo.generateSASURL(storage_account_name, video_container_name, filename, videoSASToken)
54
-
55
- # 1.1. Upload user audio if available
56
-
57
- userAudioInputFlag = False
58
-
59
- if input_audio is not None:
60
- userAudioInputFlag = True
61
- else:
62
- if (input_choice == "Explosions"):
63
- input_audio = os.path.join(os.path.dirname(__file__), "audio/1_seconds_haptic_audio.mp3")
64
- print("explosion selected")
65
- elif (input_choice == "Lightning and Thunder"):
66
- input_audio = os.path.join(os.path.dirname(__file__), "audio/8_seconds_Thunder.mp3")
67
- print("lightning and thunder selected")
68
- elif (input_choice == "Vehicle Racing"):
69
- input_audio = os.path.join(os.path.dirname(__file__), "audio/5_seconds_vehicle_audio.mp3")
70
- print("vehicle racing selected")
71
- else:
72
- input_audio = os.path.join(os.path.dirname(__file__), "audio/5_seconds_haptic_videos.mp3")
73
- print("default selected")
74
-
75
  """
76
  Processes the uploaded video (replace with your video analysis logic).
77
 
@@ -82,44 +35,16 @@ def predict_video(input_video, input_audio=None, input_choice="Explosions"):
82
  Returns:
83
  A list containing the processed video and a message string.
84
  """
85
- responseQueryText = videoAnalysis(videoSASURL, videoSASToken, input_choice)
 
86
 
87
- # IF method returns error: run analysis again
88
- if responseQueryText == """{"error":{"code":"InvalidRequest","message":"Value for indexName is invalid."}}""":
89
- responseQueryText = videoAnalysis(videoSASURL, videoSASToken, input_choice)
90
 
91
- AzureBlobStorageVideo.delete_container('useruploadhuggingfacevideo')
 
 
 
92
 
93
- json_data = load_json_output(responseQueryText)
94
-
95
- # Extract audio from the video
96
- audio_path = extract_audio_from_video(input_video)
97
- # Get explosion segments
98
- explosion_segments = get_explosion_segments(json_data)
99
-
100
- print(input_audio)
101
-
102
- # Create final audio
103
- #final_audio = create_final_audio(audio_path, explosion_segments)
104
- final_audio = create_final_audio(audio_path, input_audio, explosion_segments)
105
- # Save enhanced audio
106
- finalAudioPath = "audio/finalAudio.mp3"
107
- save_audio(final_audio, finalAudioPath)
108
-
109
- if (userAudioInputFlag == True):
110
- AzureBlobStorageVideo.delete_container('useruploadhuggingfaceaudio')
111
-
112
- # Extract video without audio
113
- current_video = without_audio(VideoFileClip(input_video))
114
-
115
- # Combine video with final audio
116
- final_video = combine_video_audio(current_video, final_audio)
117
-
118
- # Save final video
119
- save_video(final_video, "video/final_enhanced_video.mp4")
120
- finalVideoPath = "video/final_enhanced_video.mp4"
121
-
122
- return [finalVideoPath, f"Video enhancement successful"]
123
 
124
  css = """
125
  #col-container {
@@ -127,9 +52,7 @@ css = """
127
  max-width: 800px;
128
  }
129
  """
130
- video_1 = os.path.join(os.path.dirname(__file__), "video/test_video.mp4")
131
- audio_1 = os.path.join(os.path.dirname(__file__), "audio/audioTrack.mp3")
132
- search_1 = "Explosions"
133
  with gr.Blocks(css=css) as demo:
134
  with gr.Column(elem_id="col-container"):
135
  gr.HTML("""
@@ -137,57 +60,38 @@ with gr.Blocks(css=css) as demo:
137
  <h3>Welcome to the Hugging Face Space of Phone brr! We aim to create more immersive content for mobile phones with the use of haptic audio, this demo focuses on working for a very commonly used special effect of explosions hope you enjoy it.</h3>
138
 
139
  <p>Instructions:
140
- <br>Step 1: Upload your MP4 video.
141
  <br>Step 2: (Optional) Upload an MP3 audio track.
142
- <br>Step 3:(Optional) Choose the instance you want haptics to be added to
143
- <br>Step 4: Click on submit, and We'll analyse the video and suggest explosion timeframes using Azure Cognitive Services.
144
- <br>Step 5: The Haptic Audio will be mixed into the video and enhanced through AI mastering.
145
- <br>Step 6: View and download the final videoΒ withΒ haptics.
146
  </p>
147
  """)
148
 
149
- with gr.Row():
150
- with gr.Column():
151
- video_in = gr.File(label="Upload a Video", file_types=[".mp4"])
152
- with gr.Row():
153
- audio_in = gr.File(label="Optional: Upload an Audio Track", file_types=[".mp3"])
154
- with gr.Column():
155
- choice_in = gr.Dropdown(
156
- ["Explosions", "Lightning and Thunder", "Vehicle Racing"],value=callable(""),
157
- label="Choose", info="Haptic Audio will be added for the selected instance in a video",
158
- allow_custom_value=True
159
- )
160
- with gr.Row():
161
- btn_in = gr.Button("Submit", scale=0)
162
- with gr.Column():
163
- video_out = gr.Video(label="Output Video")
164
- with gr.Row():
165
- text_out = gr.Textbox(label="Output Text")
166
 
167
  gr.Examples(
168
- examples=[[video_1,audio_1]],
 
169
  fn=predict_video,
170
- inputs=[video_in, audio_in,choice_in],
171
  outputs=[video_out, text_out],
172
- #cache_examples=True # Cache examples for faster loading
173
  )
174
- with gr.Column():
175
- gr.HTML("""
176
- <h3> Audio Library </h2>
177
- <p> <a href="https://audiolibrary.blob.core.windows.net/audiolibrary/1_seconds_haptic_audio.mp3"> Explosion Audio Track 1 </a>
178
- <br> <a href="https://audiolibrary.blob.core.windows.net/audiolibrary/5_seconds_haptic_videos.mp3"> Explosion Audio Track 2 </a>
179
- <br> <a href="https://audiolibrary.blob.core.windows.net/audiolibrary/6_seconds_haptic_audio.mp3"> Explosion Audio Track 3 </a>
180
- <br> <a href="https://audiolibrary.blob.core.windows.net/audiolibrary/7_seconds_haptic_audio.mp3"> Explosion Audio Track 4 </a>
181
- <br> <a href="https://audiolibrary.blob.core.windows.net/audiolibrary/9_seconds_haptic_videos.mp3"> Explosion Audio Track 5 </a>
182
- <br> <a href="https://audiolibrary.blob.core.windows.net/audiolibrary/5_seconds_vehicle_audio.mp3"> Vehicle Audio Track 1 </a>
183
- <br> <a href="https://audiolibrary.blob.core.windows.net/audiolibrary/30_seconds_vehicle_audio.mp3"> Vehicle Audio Track 2 </a>
184
- </p>
185
- """)
186
-
187
- btn_in.click(
188
  fn=predict_video,
189
- inputs=[video_in,audio_in,choice_in],
190
  outputs=[video_out, text_out],
191
  queue=False
192
- )
 
193
  demo.launch(debug=True)
 
1
  import gradio as gr
2
  import os
 
 
 
 
 
3
  from azure.storage.blob import BlobServiceClient
4
  import AzureBlobStorageVideo
5
  import AzureBlobStorageAudio
6
+
7
+
8
+ def predict_video(input_video, input_audio=None):
 
 
 
 
 
 
 
 
 
 
9
  global filename, file_size # Use the global keyword to refer to the global variables
10
 
11
  # Check if the video is available
 
21
 
22
  if file_size > 20 * 1024 * 1024:
23
  return [None, "Error: The upload exceeds file size 16MB. Please upload a smaller file."]
24
+
25
+ #upload the video to AzureBlobStorage
26
+ AzureBlobStorageVideo.uploadUserVideoToBlobStorage(input_video,"test6")
27
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
28
  """
29
  Processes the uploaded video (replace with your video analysis logic).
30
 
 
35
  Returns:
36
  A list containing the processed video and a message string.
37
  """
38
+ # Placeholder processing (replace with actual video analysis)
39
+ message = "**Placeholder:** Video processing not implemented yet."
40
 
41
+ # You can optionally add a progress bar or loading indicator here
 
 
42
 
43
+ if input_audio is None:
44
+ return [input_video, message + " Generated Audio will be used"]
45
+ AzureBlobStorageAudio.uploadUserAudioToBlobStorage(input_audio,"test8")
46
+ return [input_video, message + f" Using uploaded audio: {input_audio.name}"]
47
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
48
 
49
  css = """
50
  #col-container {
 
52
  max-width: 800px;
53
  }
54
  """
55
+
 
 
56
  with gr.Blocks(css=css) as demo:
57
  with gr.Column(elem_id="col-container"):
58
  gr.HTML("""
 
60
  <h3>Welcome to the Hugging Face Space of Phone brr! We aim to create more immersive content for mobile phones with the use of haptic audio, this demo focuses on working for a very commonly used special effect of explosions hope you enjoy it.</h3>
61
 
62
  <p>Instructions:
63
+ <br>Step 1: Upload your video.
64
  <br>Step 2: (Optional) Upload an MP3 audio track.
65
+ <br>Step 3: We'll analyze the video and suggest explosion timeframes using Azure Cognitive Services (not included yet).
66
+ <br>Step 4: Download haptic explosion audio from [link to audio source].
67
+ <br>Step 5: Mix the Audio using any app of your choice and master the audio with an AI mastering program (links provided).
 
68
  </p>
69
  """)
70
 
71
+ with gr.Row():
72
+ with gr.Column():
73
+ video_in = gr.File(label="Upload a Video", file_types=[".mp4"])
74
+ with gr.Column():
75
+ audio_in = gr.File(label="Optional: Upload an Audio Track", file_types=[".mp3"])
76
+ with gr.Column():
77
+ video_out = gr.Video(label="Output Video")
78
+ with gr.Row():
79
+ text_out = gr.Textbox(label="Output Text")
 
 
 
 
 
 
 
 
80
 
81
  gr.Examples(
82
+ examples=[[os.path.join(os.path.dirname(__file__), "video/test_video.mp4"),
83
+ os.path.join(os.path.dirname(__file__), "video/audioTrack.mp3")]],
84
  fn=predict_video,
85
+ inputs=[video_in, audio_in],
86
  outputs=[video_out, text_out],
87
+ cache_examples= False # Cache examples for faster loading
88
  )
89
+
90
+ video_in.change(
 
 
 
 
 
 
 
 
 
 
 
 
91
  fn=predict_video,
92
+ inputs=[video_in, audio_in], # Use both video and audio inputs here
93
  outputs=[video_out, text_out],
94
  queue=False
95
+ )
96
+
97
  demo.launch(debug=True)
audio/1_seconds_haptic_audio.mp3 DELETED
Binary file (70.1 kB)
 
audio/5_seconds_haptic_videos.mp3 DELETED
Binary file (204 kB)
 
audio/5_seconds_vehicle_audio.mp3 DELETED
Binary file (81.1 kB)
 
audio/8_seconds_Thunder.mp3 DELETED
Binary file (170 kB)
 
audio/audioTrack.mp3 DELETED
Binary file (81.1 kB)
 
mastering.py DELETED
@@ -1,7 +0,0 @@
1
- import subprocess
2
-
3
- def masterAudio(inputPath,outputPath):
4
- try:
5
- master = subprocess.run(["node", "masteringModule/main.js", "--input", inputPath, "--output", outputPath])
6
- except subprocess.CalledProcessError as err:
7
- print("Error running Mastering Module: ", err)
 
 
 
 
 
 
 
 
masteringModule/.gitignore ADDED
@@ -0,0 +1,81 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Created by https://www.gitignore.io/api/node
2
+
3
+ ### Node ###
4
+ # Logs
5
+ logs
6
+ *.log
7
+ npm-debug.log*
8
+ yarn-debug.log*
9
+ yarn-error.log*
10
+
11
+ # Runtime data
12
+ pids
13
+ *.pid
14
+ *.seed
15
+ *.pid.lock
16
+
17
+ # Directory for instrumented libs generated by jscoverage/JSCover
18
+ lib-cov
19
+
20
+ # Coverage directory used by tools like istanbul
21
+ coverage
22
+
23
+ # nyc test coverage
24
+ .nyc_output
25
+
26
+ # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
27
+ .grunt
28
+
29
+ # Bower dependency directory (https://bower.io/)
30
+ bower_components
31
+
32
+ # node-waf configuration
33
+ .lock-wscript
34
+
35
+ # Compiled binary addons (https://nodejs.org/api/addons.html)
36
+ build/Release
37
+
38
+ # Dependency directories
39
+ node_modules/
40
+ jspm_packages/
41
+
42
+ # TypeScript v1 declaration files
43
+ typings/
44
+
45
+ # Optional npm cache directory
46
+ .npm
47
+
48
+ # Optional eslint cache
49
+ .eslintcache
50
+
51
+ # Optional REPL history
52
+ .node_repl_history
53
+
54
+ # Output of 'npm pack'
55
+ *.tgz
56
+
57
+ # Yarn Integrity file
58
+ .yarn-integrity
59
+
60
+ # dotenv environment variables file
61
+ .env
62
+
63
+ # parcel-bundler cache (https://parceljs.org/)
64
+ .cache
65
+
66
+ # next.js build output
67
+ .next
68
+
69
+ # nuxt.js build output
70
+ .nuxt
71
+
72
+ # vuepress build output
73
+ .vuepress/dist
74
+
75
+ # Serverless directories
76
+ .serverless
77
+
78
+
79
+ # End of https://www.gitignore.io/api/node
80
+
81
+ /output.wav
mixing.py CHANGED
@@ -20,7 +20,6 @@ def mixingAudio(sound1_path, sound2_path,position):
20
  sound1_path = check_and_convert(sound1_path)
21
  sound2_path = check_and_convert(sound2_path)
22
 
23
- # Load audio files
24
  sound1 = AudioSegment.from_file(sound1_path)
25
  sound2 = AudioSegment.from_file(sound2_path)
26
 
@@ -29,4 +28,10 @@ def mixingAudio(sound1_path, sound2_path,position):
29
 
30
  # Save the result (assuming mp3 format)
31
  output.export(r"mixedAudio\mixed_haptic_audioFile.mp3", format="mp3")
32
- return "The audio has been mixed."
 
 
 
 
 
 
 
20
  sound1_path = check_and_convert(sound1_path)
21
  sound2_path = check_and_convert(sound2_path)
22
 
 
23
  sound1 = AudioSegment.from_file(sound1_path)
24
  sound2 = AudioSegment.from_file(sound2_path)
25
 
 
28
 
29
  # Save the result (assuming mp3 format)
30
  output.export(r"mixedAudio\mixed_haptic_audioFile.mp3", format="mp3")
31
+ return "The audio have been mixed."
32
+
33
+
34
+ # for testing
35
+ # sound1_path = r"audio\mixkit-distant-explosion-1690.wav"
36
+ # sound2_path = r"audio\videoplayback_mastered (1).wav"
37
+ # mixingAudio(sound1_path, sound2_path,1000)
video/audioTrack.mp3 ADDED
Binary file (496 kB). View file