Splitting a wav file into multiple files for an Android application - android

I need to split a given .wav file into 1 second wav files for an android application. Is there any library I can use and if not what method should I follow.

here is a bash shell script which splits a wav file into 1 second clips by calling ffmpeg ... I run this on my linux laptop ... I do not know whether ffmpeg is available on android it is available as a library callable from say c or java
#!/bin/bash
# https://stackoverflow.com/questions/50087271/how-to-preprocess-audio-data-for-input-into-a-neural-network/50088265#50088265
# Split a wav file into multiple optionally overlapping .wav files using ffmpeg
# https://stackoverflow.com/questions/51188268/split-a-wav-file-into-multiple-overlapping-wav-files-using-ffmpeg
input_audio=${HOME}/Lee_Smolin_Physics_Envy_and_Economic_Theory-cWn86ESze6M_mono_1st_few_seconds.wav
# input_audio=${HOME}/Lee_Smolin_Physics_Envy_and_Economic_Theory-cWn86ESze6M_mono_1st_few_seconds.mp3
output_dir="./output_v08"
if [[ ! -d "$output_dir" ]]; then
echo "mkdir -p ${output_dir}"
mkdir -p "${output_dir}"
fi
# output_audio_prefix=output_v03/aaa
output_audio_prefix="${output_dir}/aaa"
snip_duration=1.0 # in seconds
# snip_duration=1.5 # in seconds
# https://ffmpeg.org/ffmpeg.html
# https://ffmpeg.org/ffmpeg-utils.html#time-duration-syntax
# ffmpeg -i input.mp3 -ss 10 -t 6 -acodec copy output.mp3
# ffmpeg -i $input_audio -ss 0 -t 1 -acodec copy $output_audio_prefix
:<<'good_here' # this is a bulk comment to show an example of what below loop is doing
ffmpeg -i $input_audio -ss 0 -t $snip_duration -acodec copy ${output_audio_prefix}.0.00.wav
ffmpeg -i $input_audio -ss 0.20 -t $snip_duration -acodec copy ${output_audio_prefix}.0.20.wav
ffmpeg -i $input_audio -ss 0.40 -t $snip_duration -acodec copy ${output_audio_prefix}.0.40.wav
ffmpeg -i $input_audio -ss 0.60 -t $snip_duration -acodec copy ${output_audio_prefix}.0.60.wav
ffmpeg -i $input_audio -ss 0.80 -t $snip_duration -acodec copy ${output_audio_prefix}.0.80.wav
ffmpeg -i $input_audio -ss 1.00 -t $snip_duration -acodec copy ${output_audio_prefix}.1.00.wav
good_here
start_point=0 # start from beginning of audio file
# slide_window_over_time=500 # in milliseconds
slide_window_over_time=1000 # in milliseconds
# ffmpeg -i $input_audio -af astats -f null -
echo input_audio $input_audio
if [[ ! -f $input_audio ]]; then
echo "ERROR - input file does not exist -->$input_audio<-- "
exit
fi
# duration_input_audio=$( ffprobe -i $input_audio -show_entries format=duration -v quiet -of csv="p=0" | bc * 1000 )
duration_input_audio=$( ffprobe -i $input_audio -show_entries format=duration -v quiet -of csv="p=0" )
echo duration_input_audio $duration_input_audio
duration_in_milli_float=$( echo "$duration_input_audio * 1000" | bc )
echo duration_in_milli_float $duration_in_milli_float
duration_in_milli_int=${duration_in_milli_float%.*}
echo duration_in_milli_int $duration_in_milli_int
echo start_point $start_point
for((curr_window_start=$start_point;$curr_window_start<=$duration_in_milli_int;)) do
echo curr_window_start $curr_window_start
curr_window_start_seconds=$( echo "$curr_window_start / 1000" | bc -l )
echo curr_window_start_seconds $curr_window_start_seconds
curr_output_file=${output_audio_prefix}.${curr_window_start_seconds}.wav
echo curr_output_file $curr_output_file
# ffmpeg -i $input_audio -ss 0.60 -t $snip_duration -acodec copy ${output_audio_prefix}.0.60.wav
ffmpeg -i $input_audio -ss $curr_window_start_seconds -t $snip_duration -acodec copy ${curr_output_file}
# ...
curr_window_start=$( echo "$curr_window_start + $slide_window_over_time" | bc )
done
# .......... above can also be achieved directly by executing
# echo
# echo above can also be achieved directly by executing
# echo
# ffprobe -f lavfi -i amovie=${input_audio},astats=metadata=1:reset=1 -show_entries frame=pkt_pts_time:frame_tags=lavfi.astats.Overall.RMS_level,lavfi.astats.1.RMS_level,lavfi.astats.2.RMS_level -of csv=p=0
above works however you can certainly roll your own code in say java to split a wav file into clips ... it may take a couple days of coding or less once up to speed on digital audio, make that a couple of weeks if starting from a stand still as it involves notions like data endianness and multi byte storage of say 16 bit integers

Related

FFMPEG SlideShow - Only display first frame

I m using below ffmpeg command to generate video(slideshow) from list of images,but the issue is that its only displaying first image.
ffmpeg -loop 1 -t 3 -i image1.jpg -i image2.jpg -i image3.jpg -filter_complex [v][v1][v2] concat=n=3:v=1,format=yuv422p[a] -map [a] out.mp4
Any help will be appreciate.
Thanks.
Finally after lot of practices got the solution and better ffmpeg command then above command.
ffmpeg -f concat -safe 0 -i img-list.txt -f concat -safe 0 -i audio-list.txt -c:a aac -pix_fmt yuv420p -crf 23 -r 24 -shortest -y -vf "scale=trunc(iw/2)*2:trunc(ih/2)*2" video.mp4
in above command input.txt will contains path of image files seperated with new line.
input.txt
file '*/image1.jpg'
file '*/image2.jpg'
file '*/image3.jpg'

Splitting audio tracks with incorrect length - FFMPEG

Version: com.writingminds:FFmpegAndroid:0.3.2
I have an audio file with length 43 seconds. And I wrote an algorithm to split at each 10 seconds mark where a word ends (For this I used IBM Watson to get ending timestamp). So cropping duration is always around 10 seconds to 11 seconds. Of course except the 5th one. I have printed my commands so that you will understand my use-case better.
System.out: Split Command: -y -i /storage/emulated/0/AudioClipsForSpeakerRecognition/merge.wav -ss 00:00:00.000 -codec copy -t 00:00:10.010 /storage/emulated/0/AudioClipsForSpeakerRecognition/segment_1.wav
System.out: Split Command: -y -i /storage/emulated/0/AudioClipsForSpeakerRecognition/merge.wav -ss 00:00:10.010 -codec copy -t 00:00:21.090 /storage/emulated/0/AudioClipsForSpeakerRecognition/segment_2.wav
System.out: Split Command: -y -i /storage/emulated/0/AudioClipsForSpeakerRecognition/merge.wav -ss 00:00:21.090 -codec copy -t 00:00:30.480 /storage/emulated/0/AudioClipsForSpeakerRecognition/segment_3.wav
System.out: Split Command: -y -i /storage/emulated/0/AudioClipsForSpeakerRecognition/merge.wav -ss 00:00:30.480 -codec copy -t 00:00:40.120 /storage/emulated/0/AudioClipsForSpeakerRecognition/segment_4.wav
System.out: Split Command: -y -i /storage/emulated/0/AudioClipsForSpeakerRecognition/merge.wav -ss 00:00:40.120 -codec copy -t 00:00:43.000 /storage/emulated/0/AudioClipsForSpeakerRecognition/segment_5.wav
However when playing all cropped audio files I noticed segment_1 is about 10 seconds and segment_2 is about 20 seconds etc. Therefore some of the audio parts belong to segment_1 also available in segment 2 etc etc. Why is this happening?
Appreciate your response.
-t represents duration. Use -to instead.

FFmpeg concat with absolute path

I try to concatenate two videos using ffmpeg I use that wrapper: wrapper.
According docs I use this commands :
ffmpeg -i input1.mp4 -c copy -bsf:v h264_mp4toannexb -f mpegts intermediate1.ts
ffmpeg -i input2.mp4 -c copy -bsf:v h264_mp4toannexb -f mpegts intermediate2.ts
ffmpeg -i concat:"intermediate1.ts|intermediate2.ts" -c copy -bsf:a aac_adtstoasc output.mp4
After two command I got two files:
/storage/emulated/0/recorder/test1_convert.ts /storage/emulated/0/recorder/test2_convert.ts
But when I execute the third command I got failure: log message: concat:"/storage/emulated/0/recorder/test1_convert.ts|/storage/emulated/0/recorder/test2_convert.ts": No such file or directory
I suppose something wrong with syntax absolute path. This is full my third command:
Remove the double-quotes in the concat line.
I am not an Android user but quoting seems to be a typical problem on Android when using ffmpeg.

FFmpeg command for crossfading between 5 videos .How to manage setpts=PTS-STARTPTS?

Here, New in FFmpeg . I am using and testing in console in FFmpeg .
I already done with 2 video join with cross fading with this question :
I am doing for 5 videos merging with cross fade I just done 90% in merging
i just need to manage setpts=PTS-STARTPTS Just look into this pls.
ffmpeg -i big_buck.mp4 -i big_buck.mp4 -i big_buck.mp4 -i big_buck.mp4 -i
big_buck.mp4 -filter_complex "[0:v]trim=0:4,setpts=PTS-
STARTPTS,fade=out:st=4:d=1:alpha=1[1]; [1:v]trim=1:4,setpts=PTS-
STARTPTS,format=yuva420p,fade=in:st=0:d=1:alpha=1,fade=out:st=4:d=1:alpha=1[2];
[2:v]trim=1:4,setpts=PTS-
STARTPTS,format=yuva420p,fade=in:st=0:d=1:alpha=1,fade=out:st=4:d=1:alpha=1[3];
[3:v]trim=1:4,setpts=PTS-
STARTPTS,format=yuva420p,fade=in:st=0:d=1:alpha=1,fade=out:st=4:d=1:alpha=1[4];
[4:v]trim=1:4,setpts=PTS-STARTPTS,format=yuva420p,fade=in:st=0:d=1:alpha=1[5];
[1][2]overlay,format=yuv420p[12]; [12][3]overlay,format=yuv420p[123]; [4]
[5]overlay,format=yuv420p[45]; [123][45]concat=n=2 [v]" -map [v] result.mp4
****Note that every input video big_buck.mp4 length is 5 sec ****. now see setpts=PTS-STARTPTS in code How to Manage that in every video Input????
I also see in variuos forums about that but i didnt find!!!
Thank you
Use
ffmpeg -i big_buck.mp4 -i big_buck.mp4 -i big_buck.mp4 -i big_buck.mp4 -i
big_buck.mp4 -filter_complex \
"[0:v]setpts=PTS-STARTPTS[v1]; \
[1:v]format=yuva420p,fade=in:st=0:d=1:alpha=1,setpts=PTS-STARTPTS+(4/TB)[v2];
[2:v]format=yuva420p,fade=in:st=0:d=1:alpha=1,setpts=PTS-STARTPTS+(8/TB)[v3];
[3:v]format=yuva420p,fade=in:st=0:d=1:alpha=1,setpts=PTS-STARTPTS+(12/TB)[v4];
[4:v]format=yuva420p,fade=in:st=0:d=1:alpha=1,setpts=PTS-STARTPTS+(16/TB)[v5];
[v1][v2]overlay[v12]; [v12][v3]overlay[v123]; [v123][v4]overlay[v1234]; [v1234][v5]overlay,format=yuv420p[v]" \
-map [v] result.mp4
The PTS has to be modified so that each new clip starts 1 second before the current combination of clips ends i.e. the 3rd clip should start fading in at 8 seconds, since the combination of the first two clips is 9 seconds (4 seconds of first clip + 1 second transition + 4 seconds of 2nd clip).
You don't need the fade out as the next clip is fading in on top. The concat is only required if you want a cut.
With audio crossfades:
ffmpeg -i big_buck.mp4 -i big_buck.mp4 -i big_buck.mp4 -i big_buck.mp4 -i
big_buck.mp4 -filter_complex \
"[0:v]setpts=PTS-STARTPTS[v1]; \
[1:v]format=yuva420p,fade=in:st=0:d=1:alpha=1,setpts=PTS-STARTPTS+(4/TB)[v2];
[2:v]format=yuva420p,fade=in:st=0:d=1:alpha=1,setpts=PTS-STARTPTS+(8/TB)[v3];
[3:v]format=yuva420p,fade=in:st=0:d=1:alpha=1,setpts=PTS-STARTPTS+(12/TB)[v4];
[4:v]format=yuva420p,fade=in:st=0:d=1:alpha=1,setpts=PTS-STARTPTS+(16/TB)[v5];
[v1][v2]overlay[12]; [12][v3]overlay[123]; [123][v4]overlay[1234]; [1234][v5]overlay,format=yuv420p[v]; \
[1][2]acrossfade=d=1[a12]; [a12][3]acrossfade=d=1[a123]; [a123][4]acrossfade=d=1[a];" \
-map [v] -map [a] result.mp4
Based on the Gyan's answer I have created a convenient Bash script video_crossfade.sh to crossfade any number of videos of different duration.
#!/bin/bash
INPUT="$1"
CMD="ffmpeg"
SIZE=$(find . -iname "$INPUT" | wc -l)
if (( SIZE < 2 ))
then
echo "2 or more videos are required"
exit 1
fi
VIDEO=""
OUT=""
i="0"
total_duration="0"
for file in $(find . -iname "$INPUT" | sort)
do
echo $file
CMD="$CMD -i $file"
duration=$(ffprobe -v error -select_streams v:0 -show_entries stream=duration -of csv=p=0 "$file" | cut -d'.' -f1)
if [[ "$i" == "0" ]]
then
VIDEO="[0:v]setpts=PTS-STARTPTS[v0];"
else
fade_start=$((total_duration-$i))
VIDEO="${VIDEO}[${i}:v]format=yuva420p,fade=in:st=0:d=1:alpha=1,setpts=PTS-STARTPTS+(${fade_start}/TB)[v${i}];"
if (( i < SIZE-1 ))
then
if (( i == 1 ))
then
OUT="${OUT}[v0][v1]overlay[outv1];"
else
OUT="${OUT}[outv$((i-1))][v${i}]overlay[outv${i}];"
fi
else
if (( SIZE == 2 ))
then
OUT="${OUT}[v0][v1]overlay,format=yuv420p[outv]"
else
OUT="${OUT}[outv$((i-1))][v${i}]overlay,format=yuv420p[outv]"
fi
fi
fi
total_duration=$((total_duration+duration))
i=$((i+1))
done
CMD="$CMD -filter_complex \"${VIDEO}${OUT}\" -c:v libx264 -map [outv] crossfade.MP4"
echo "$CMD"
bash -c "$CMD"
Example:
./video_crossfade.sh '*.MP4'
Result:
The script takes all videos form by wildcard pattern and uses ffprobe to get the video duration.

Unable to concatenate videos due to identical MOOV atoms

I am cutting out segments from a long mp4 file and then rejoining parts of them. However, since FFMPEG apparently keeps the same MOOV atom for the trimmed files as the original, it looks to FFMPEG that the trimmed videos are all identical since they all have the same MOOV atom, and therefore only uses the first segment when trying to join the videos. Is there a way around this? Unfortunately since FFMPEG is embedded in an Android app, I can only use version 0.11.
Edit:
This is a sample of the processes:
ffmpeg -i /sdcard/path/movie.mp4 -ss 00:00:06.000, -t 00:00:05.270, -c:a aac -c:v libx264 /sdcard/path/file1.mp4
ffmpeg -i /sdcard/path/movie.mp4 -ss 00:00:12.000, -t 00:00:04.370, -c:a aac -c:v libx264 /sdcard/path/file2.mp4
ffmpeg -i /sdcard/path/movie.mp4 -ss 00:00:23.000, -t 00:00:03.133, -c:a aac -c:v libx264 /sdcard/path/file3.mp4
ffmpeg -i "concat:/sdcard/path/file1.mp4|/sdcard/path/file2.mp4|/sdcard/path/file3.mp4" -c:a aac -c:v libx264 /sdcard/path/output.mp4
I've also tried using the copy codec option but that hasn't helped.
Can you try something like:
ffmpeg -i input1.mp4 -c copy -bsf:v h264_mp4toannexb -f mpegts intermediate1.ts
ffmpeg -i input2.mp4 -c copy -bsf:v h264_mp4toannexb -f mpegts intermediate2.ts
ffmpeg -i "concat:intermediate1.ts|intermediate2.ts" -c copy -bsf:a aac_adtstoasc output.mp4
I hope this works with ffmpeg version 0.11. We need to make sure you can concat before applying the cut of file.
Also can you check the intermediary file*.mp4 works well? Can you try to put your video files on the same folder as ffmpeg I am not sure how the concat protocol reacts to /sdcard/path/file1.mp4|/sdcard/path/file2.mp4?

Categories

Resources