Using afconvert command line tool to convert .mp3 files to m4r - bash

I have a short bash script that is meant to convert a folder full of .mp3 files to .m4r ringtones. I am having trouble figuring out why it is throwing the following error:
"Error: ExtAudioFileCreateWithURL failed ('fmt?')"
#!/bin/bash
cd "/path/to/directory/containing/mp3s"
for i in *.mp3; do
baseFilename=$( basename ${i} .mp3 )
afconvert -f m4af ${i} -o "/path/to/new/location/${baseFilename}.m4r"
done
exit 0

The issue was that I had not specified the output data format. Found a helpful page that lead me to the answer:
http://support.moonpoint.com/os/os-x/audio/afconvert.php
#!/bin/bash
cd "/path/to/directory/containing/mp3s"
for i in *.mp3; do
baseFilename=$( basename "${i}" .mp3 )
afconvert -f m4af "${i}" -d aac "/path/to/new/location/${baseFilename}.m4r"
done
exit 0

Related

Make gif (ffmpeg) using MOST RECENT 7 jpg files in a directory

I have a bash script which runs on a cron, to take screenshots of my cctv 1x per day to do an annual timelapse. It all works, and I get a YTD sofar.gif of the very first screenshot to the very last screenshot -- which is now quite long. I wanted to add a line to make last7days.gif so I could get a shorter weekly gif etc.
I have searched this site and the web and can list the newest 7 files in terminal using: ls -1t | head -n 9 | tail -n 7 (this removes the .gif and .mov which are modified last) but I do not know how to make that vertical list of 7 filenames into a variable to make a gif using those file names
# runs from a cronjob. saves live screenshot from CCTV to jpg, then updates the year-to-date movie
if [ $# -ne 1 ]
then
echo "Usage: `basename $0` OUTDIR"
exit 65
fi
doexit=0
start=$(date +%s)
end=$(date +%s)
outdir=${1%/}
mkdir $outdir
echo "Capturing image..."
counter=$(date +"%Y_%m_%d_%H-%M-%S");
file=$outdir/$counter.jpg
if response=$(curl --silent --write-out %{http_code} --max-time 600 'URL REDACTED' -o $file) ; then
echo "Captured & saved $file!"
else
echo "Failed to capture $file"
fi
ffmpeg -hide_banner -loglevel panic -pattern_type glob -i $outdir/'*.jpg' $outdir/sofar.mov -y
ffmpeg -hide_banner -loglevel panic -pattern_type glob -i $outdir/'*.jpg' $outdir/sofar.gif -y
exit 1
Currently, the last lines create a .gif using every image file, this works only because they are saved with the date in the filename.
I want to add a line to create a .gif using just the most 7 recent images
Do the globbing in the shell, then you can take whatever subset you want:
#!/usr/bin/env bash
# ^^^^- NOT /bin/sh; array support is required.
shopt -s nullglob
files=( "$outdir"/*.jpg )
file_count=${#files[#]}
if (( ${#files[#]} == 0 )); then
echo "ERROR: No files found" >&2; exit 1;
elif (( ${#files[#]} > 7 )); then
files=( "${files[#]:$(( ${#files[#]} - 7 ))}" )
fi
input_args=( )
for f in "${files[#]}"; do
input_args+=( -i "$f" )
done
ffmpeg "${input_args[#]}" "$outdir/sofar.gif"

List files in a folder in natural order using bash script

I am trying to merge several flv files using ffmpeg. ffmpeg requires a list of files in this format:
file '/path/to/file1'
file '/path/to/file2'
file '/path/to/file3'
With some search and trials, I have came up with this one line command:
ffmpeg -safe 0 -f concat -i <(for entry in "$(cd "$(dirname "$1")"; pwd)/$(basename "$1")"/*.flv;do echo "file '$entry'";done) -c copy output.flv
The script in brackets will generate a list of paths to all files in current folder in the format that is required by ffmpeg:
for entry in "$(cd "$(dirname "$1")"; pwd)/$(basename "$1")"/*.flv;do echo "file '$entry'";done
However, this only list files in alphanumeric order:
6846641-10.flv
6846641-11.flv
6846641-12.flv
6846641-13.flv
6846641-14.flv
6846641-15.flv
6846641-16.flv
6846641-17.flv
6846641-18.flv
6846641-19.flv
6846641-1.flv
6846641-20.flv
6846641-21.flv
6846641-22.flv
6846641-23.flv
6846641-24.flv
6846641-2.flv
6846641-3.flv
6846641-4.flv
6846641-5.flv
6846641-6.flv
6846641-7.flv
6846641-8.flv
6846641-9.flv
To merge videos correctly, I need files to be listed in natural order like this:
Naturally ordered files
As shown in the picture, files need to be sorted by the number after - from 1 to 24, with 6846641-1.flv in the first line and 6846641-24.flv in the last line. And each line in the format like this:
file '/mnt/c/Users/Oho/Desktop/save//6846641-xx.flv'
Would it be possible to generate a correctly formatted list for ffmpeg with bash script (and in one line if achievable)?
Edit:
Thanks to Cyrus, the modified code is here and it does the job:
#!/bin/bash
for entry in "$(cd "$(dirname "$1")"; pwd)/$(basename "$1")"/*.flv
do
echo "file '$entry'" >> fileOutputList.temp
done
sort -t "-" -n -k 2 fileOutputList.temp > fileOutputListSorted.temp
ffmpeg -safe 0 -f concat -i fileOutputListSorted.temp -c copy output.flv
rm fileOutputList.temp
rm fileOutputListSorted.temp
I suggest:
sort -t "-" -n -k 2 file
-t "-": use - as separator
-n: compare according to string numerical value
-k2,2: start a key at column 2

youtube-dl problems (scripting)

Okay, so I've got this small problem with a bash script that I'm writing.
This script is supposed to be run like this:
bash script.sh https://www.youtube.com/user/<channel name>
OR
bash script.sh https://www.youtube.com/user/<random characters that make up a youtube channel ID>
It downloads an entire YouTube channel to a folder named
<uploader>{<uploader_id>}/
Or, at least it SHOULD...
the problem I'm getting is that the archive.txt file that youtube-dl creates is not created in the same directory as the videos. It's created in the directory from which the script is run.
Is there a grep or sed command that I could use to get the archive.txt file to the video folder?
Or maybe create the folder FIRST, then cd into it, and run the command from there?
I dunno
Here is my script:
#!/bin/bash
pwd
sleep 1
echo "You entered: $1 for the URL"
sleep 1
echo "Now downloading all videos from URL "$1""
youtube-dl -iw \
--no-continue $1 \
-f bestvideo+bestaudio --merge-output-format mkv \
-o "%(uploader)s{%(uploader_id)s}/[%(upload_date)s] %(title)s" \
--add-metadata --download-archive archive.txt
exit 0
I ended up solving it with this:
uploader="$(youtube-dl -i -J $URL --playlist-items 1 | grep -Po '(?<="uploader": ")[^"]*')"
uploader_id="$(youtube-dl -i -J $URL --playlist-items 1 | grep -Po '(?<="uploader_id": ")[^"]*')"
uploaderandid="$uploader{$uploader_id}"
echo "Uploader: $uploader"
echo "Uploader ID: $uploader_id"
echo "Folder Name: $uploaderandid"
echo "Now downloading all videos from URL "$URL" to the folder "$DIR/$uploaderandid""
Basically I had to parse the JSON with grep, since the youtube-dl devs said that implementing -o type variables into any other variable would clog up the code and make it bloated.

Bad bitrate in 3gp file, convert to mp3 using ffmpeg

I record calls on my phone (as audio only). Records are storing to 3gp file. When I play a single file it can be mentioned that it is plaing few times faster then normal speed of conversation. I tested, that played on ffplay using command
ffplay.exe %1 -ar 8000
sounds as a real speed.
I would like to convert 3gp file to mp3 file using ffmpeg file (easy batch script running on Windows). I started with command line
ffmpeg.exe -i %1 -ar 8000 -f mp3 %1.mp3
but bitaire of mp3 don't sounds well (too fast). I performed experiments with -b, -b:a and others parameters but bitrate does not change.
Which parameters have I use to change 3gp to mp3 file with proper bitrate value?
-ar 8000
forces ffmpeg to interpret your input file as being sampled at 8kHz. Is tis the case or are you trying to downsample it to 8 kHz?
If so try the following instead:
-af "aresample=8000"
Please mark this as good answer if you're happy with it ;)
Well the commands you have fired are correct. I myself tried them myself and are working correctly. So firstly just try again with 1 file rather than batch files.
Here is command 1
ffmpeg -i input.3gp -ar 32k -f mp3 out.mp3
Result
Bitrate of out.mp3 is 47kbps
Command 2
ffmpeg -i inout.3gp -b:a 32k out.mp3
Bitrate of out.mp3 32kbps
So you can go with any of the above.
Cheers :)
Below you will find a script that I altered to include .3gp files.
It also does .mp4 .mkv and .webm files.
The clarity of the voice was good at 30k and that is what is here, but if you want larger files with better sound clarity then try 200k.
Call your script file vidconvmp3.sh for example and save it.
Then Modch +x vidconvmp3.sh to authorize execute.
then ./vidconvmp3.sh and your batch will run through and toss your mp3 files into a folder called Desktop-mp3 if you run terminal on the desktop... tah dah.
#!/usr/bin/env bash
# My bash Script to convert mp4 to mp3
# By NerdJK23
# web: www.computingforgeeks.com
# email: kiplangatmtai#gmail.com
# Requires
# ffmpeg installed
# lame installed
# Check https://computingforgeeks.com/how-to-convert-mp4-to-mp3-on-linux/
echo -ne """
1: Current directory
2: Provide directory
"""
echo ""
echo -n "Selection : "
read selection
case $selection in
1)
echo "Okay.."
echo ""
echo "Current dir is `pwd` "
;;
2)
echo ""
echo -n "Give diretory name: "
read dir_name
# Check if given directory is valid
if [ -d $dir_name ]; then
cd "${$dir_name}"
echo "Current directory is `pwd` "
echo
else
echo "Invalid directory, exiting.."
echo ""
exit 10
fi
echo
;;
*)
echo
echo "Wrong selection"
exit 11
;;
esac
echo ""
# Create dir to store mp3 files if it doesn't exist
# First get the current directory name
current_dir=`pwd`
base_name=` basename "$current_dir"`
if [[ ! -d "$base_name"-mp3 ]]; then
echo "$base_name" | xargs -d "\n" -I {} mkdir {}-mp3
echo ""
fi
echo ""
# Bigin to covert videos to mp3 audio files
# -d "\n" > Change delimiter from any whitespace to end of line character
find . -name "*.mp4" -o -name "*.mkv" -o -name "*.webm" -o -name "*.3gp" | xargs -d "\n" -I {} ffmpeg -i {} -b:a 30K -vn "$base_name"-mp3/{}.mp3
# remove video extensions
cd "${base_name}"-mp3
for file_name in *; do
mv "$file_name" "`echo $file_name | sed "s/.mp4//g;s/.mkv//g;s/.3pg//g;s/.webm//g"`";
done
# Move audio directory to ~/Music
if [[ ! -d ~/Music ]]; then
mkdir ~/Music
fi
cd ..
mv "$base_name"-mp3 ~/Music/
# Check if conversion successfull
echo ""
if [[ $? -eq "0" ]];then
echo " All files converted successfully"
else
echo "Conversation failed"
exit 1
fi

bash for command

#!/bin/bash
for i in /home/xxx/sge_jobs_output/split_rCEU_results/*.rCEU.bed
do
intersectBed -a /home/xxx/sge_jobs_output/split_rCEU_results/$i.rCEU.bed -b /home/xxx/sge_jobs_output/split_NA12878_results/$i.NA12878.bed -f 0.90 -r > $i.overlap_90.bed
done
However I got the errors like:
Error: can't determine file type of '/home/xug/sge_jobs_output/split_NA12878_results//home/xug/sge_jobs_output/split_rCEU_results/chr4.rCEU.bed.NA12878.bed': No such file or directory
Seems the computer mixes the two .bed files together, and I don't know why.
thx
Your i has the format /home/xxx/sge_jobs_output/split_rCEU_results/whatever.rCEU.bed, and you insert it to the file name, which leads to the duplication. It's probably simplest to switch to the directory and use basename, like this:
pushd /home/xxx/sge_jobs_output/split_rCEU_results
for i in *.rCEU.bed
do
intersectBed -a $i -b ../../sge_jobs_output/split_NA12878_results/`basename $i .rCEU.bed`.NA12878.bed -f 0.90 -r > `basename $i .NA12878.bed`.overlap_90.bed
done
popd
Notice the use of basename, with which you can replace the extension of a file: If you have a file called filename.foo.bar, basename filename.foo.bar .foo.bar returns just filename.

Resources