I'm working on an android app that converts the text into corresponding video and I'm using python and java for it. The videos are stored in assets directory of android studio. The model accesses the asset directory but doesn't read the data. Here's my code
#python
import cv2
import numpy as np
import spacy
import nltk
from nltk.corpus import wordnet
from itertools import chain
import os
import time
AssetManager = Python.getPlatform().getApplication().getAssets()
nltk.download('wordnet')
# Load the SpaCy language model
nlp = spacy.load("en_core_web_sm")
# Function to process text and concatenate videos
def process_text_and_generate_video(input_text, asset_manager, context):
word=''
# Tokenize using spacy
doc = nlp(input_text)
# Initialize a dictionary to map POS tags
pos_dict = {"NOUN": "noun", "VERB": "verb", "ADJ": "adj", "ADV": "adv", "PRON": "pron", "ADP": "adp"}
# Array to store video frames
frames = []
# Iterate through spacy's tokenized results
for token in doc:
word = token.text
pos_tag = token.pos_
if pos_tag in pos_dict:
try:
# Copy the video file from assets to a temporary directory
file_path = f"assets/{word}.mp4"
print(f"Trying to open file: {file_path}")
with asset_manager.open(file_path) as fd:
temp_file_path = os.path.join(context.getCacheDir(), f"{word}.mp4")
with open(temp_file_path, 'wb') as out:
out.write(fd.read())
# Read video frames into a numpy array
cap = cv2.VideoCapture(temp_file_path)
ret, frame = cap.read()
if ret:
frames.append(frame)
except Exception as e:
print(f"Exception occurred: {e}")
else:
# Get synonyms of the word
synonyms = wordnet.synsets(word)
synonyms = set(chain.from_iterable([word.lemma_names() for word in synonyms]))
# Check if any synonym has a corresponding video in the directory
for synonym in synonyms:
try:
# Copy the video file from assets to a temporary directory
file_path = f"assets/{synonym}.mp4"
print(f"Trying to open file: {file_path}")
with asset_manager.open(file_path) as fd:
temp_file_path = os.path.join(context.getCacheDir(), f"{synonym}.mp4")
with open(temp_file_path, 'wb') as out:
out.write(fd.read())
# Read video frames into a numpy array
cap = cv2.VideoCapture(temp_file_path)
ret, frame = cap.read()
if ret:
frames.append(frame)
break
except Exception as e:
print(f"Exception occurred: {e}")
# If no videos were found for the word or its synonyms, look for videos that match each letter of the word
if not frames:
for letter in word.lower(): # Convert to lowercase because file names are in lowercase.
try:
# Copy the video file from assets to a temporary directory
file_path = f"assets/{letter}.mp4"
print(f"Trying to open file: {file_path}")
with asset_manager.open(file_path) as fd:
temp_file_path = os.path.join(context.getCacheDir(), f"{letter}.mp4")
with open(temp_file_path, 'wb') as out:
out.write(fd.read())
# Read video frames into a numpy array
cap = cv2.VideoCapture(temp_file_path)
ret, frame = cap.read()
if ret:
frames.append(frame)
except Exception as e:
print(f"Exception occurred: {e}")
# If no videos were found at all, print a message and return None.
if not frames:
print("No match found")
return None
# Concatenate video frames.
final_clip = np.concatenate(frames)
# Export the concatenated video using cv2.VideoWriter().
fourcc = cv2.VideoWriter_fourcc(*'MP4V')
height, width, _ = final_clip[0].shape # get the width and height of the first frame
output_file_path = os.path.join(context.getFilesDir(), 'my_concatenation.mp4')
out = cv2.VideoWriter(output_file_path, fourcc, 30.0, (width, height))
for frame in final_clip:
out.write(frame)
out.release()
time.sleep(1)
return output_file_path if os.path.exists(output_file_path) else None
...java
package com.example.myapplication_fyppsl;
import android.content.Context;
import android.os.AsyncTask;
import android.widget.MediaController;
import android.widget.Toast;
import android.widget.VideoView;
import com.chaquo.python.PyObject;
import com.chaquo.python.Python;
import java.io.IOException;
public class VideoProcessingTask extends AsyncTask<String, Void, String> {
private VideoView videoView;
private Context context;
public VideoProcessingTask(VideoView videoView,Context context) {
this.videoView = videoView;
this.context = context;
}
@Override
protected String doInBackground(String... strings) {
String input = strings[0];
Python py = Python.getInstance();
PyObject pyf = py.getModule("displayAnimation");
try {
String[] files = context.getAssets().list("");
for(String name : files) {
System.out.println("File : " + name);
}
} catch (IOException e) {
e.printStackTrace();
}
// pass the AssetManager and get back the path of created file.
PyObject obj = pyf.callAttr("process_text_and_generate_video", input, context.getAssets(), context);
// Check if obj is null before calling toString()
return obj == null ? null : obj.toString();
}
@Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
// Check if result is None before trying to set the video path
if (result == null) {
Toast.makeText(context, "No videos found for your input.", Toast.LENGTH_SHORT).show();
return;
}
// Set the path of the Video or URI from result of doInBackground method.
videoView.setVideoPath(result);
// Create a MediaController and attach it to the VideoView
MediaController mediaController = new MediaController(context);
mediaController.setAnchorView(videoView);
// Attach the MediaController to the VideoView
videoView.setMediaController(mediaController);
// Start the VideoView
videoView.start();
}
}
I've tried many ways to find out what went wrong but I'm still unable to find it.
- Check all permissions
- Path
- Video format
- Video title
- Gradle configuration
In Java, the zero-argument
InputStream.read()
method returns only a single byte, not the entire file. You could use a helper function as shown here:Or instead of the assets directory, you could put the files in your Python source directory and open them as regular files, as shown here: