commit 656f1cf24542ae8ed45ce34c0cb1973f8235bf45
parent bf4543982493449c24d72e553c789eb76a99f384
Author: rbckman <rob@tarina.org>
Date: Wed, 2 Apr 2025 23:43:47 +0100
ok, working to write direct to mp4 wohooo!
Diffstat:
3 files changed, 99 insertions(+), 14 deletions(-)
diff --git a/extras/ffmpegmux.py b/extras/ffmpegmux.py
@@ -0,0 +1,42 @@
+import picamerax as picamera
+import subprocess
+import time
+
+quality = 20
+bitrate = 8888888
+profilelevel='4.2'
+
+# FFmpeg command to take H.264 input from stdin and output to MP4
+ffmpeg_cmd = [
+ 'ffmpeg',
+ '-i', 'pipe:0', # Input from stdin (raw H.264 from PiCamera)
+ '-c:v', 'copy', # Use hardware encoder
+ '-b:v', str(bitrate),
+ '-level:v', '4.2',
+ '-g', '1',
+ '-f', 'mp4', # Output format
+ 'output.mp4', # Output file
+ '-loglevel','debug',
+ '-y' # Overwrite output file if it exists
+]
+
+
+#'-c:v h264_omx -profile:v high -level:v 4.2 -preset slow -bsf:v h264_metadata=level=4.2 -g 1 -b:v '+str(bitrate)+' -c:a copy '
+# Start FFmpeg process
+process = subprocess.Popen(ffmpeg_cmd, stdin=subprocess.PIPE)
+
+# Initialize PiCamera
+with picamera.PiCamera() as camera:
+ camera.resolution = (1920, 1080) # High Quality Camera resolution
+ camera.framerate = 24.97
+ camera.start_preview()
+ # Start recording and pipe to FFmpeg
+ print("Starting recording...")
+ camera.start_recording(process.stdin, format='h264', bitrate = 8888888, level=profilelevel, quality=quality, intra_period=1)
+ camera.wait_recording(10) # Record for 10 seconds
+ camera.stop_recording()
+
+# Close the FFmpeg process
+process.stdin.close()
+process.wait()
+print("Recording complete!")
diff --git a/gonzopi.py b/gonzopi.py
@@ -41,6 +41,7 @@ import web
# Check for slider support
import serial
import serial.tools.list_ports
+from pymediainfo import MediaInfo
# Get a list of all serial ports
slidecommander = ''
slideports = serial.tools.list_ports.comports()
@@ -528,10 +529,10 @@ def main():
imagename = foldername + filename + '.jpeg'
overlay = displayimage(camera, imagename, overlay, 3)
camera.start_preview()
- take = counttakes(filmname, filmfolder, scene, shot)
else:
vumetermessage('nothing here! hit rec!')
playdub(filmname, renderfilename, 'shot')
+ take = counttakes(filmname, filmfolder, scene, shot)
rendermenu = True
updatethumb=True
#BLEND
@@ -1414,9 +1415,10 @@ def main():
os.system(gonzopifolder + '/alsa-utils-1.1.3/aplay/arecord -D hw:' + str(plughw) + ' -f '+soundformat+' -c ' + str(channels) + ' -r '+soundrate+' -vv '+ foldername + filename + '.wav &')
sound_start = time.time()
if onlysound != True:
- camera.start_recording(filmfolder+ '.videos/'+video_origins+'.h264', format='h264', bitrate = bitrate, level=profilelevel, quality=quality, intra_period=1)
+ #camera.start_recording(filmfolder+ '.videos/'+video_origins+'.h264', format='h264', bitrate = bitrate, level=profilelevel, quality=quality, intra_period=1)
+ rec_process=startrecording(camera, filmfolder+ '.videos/'+video_origins+'.mp4')
starttime = time.time()
- os.system('ln -sfr '+filmfolder+'.videos/'+video_origins+'.h264 '+foldername+filename+'.h264')
+ os.system('ln -sfr '+filmfolder+'.videos/'+video_origins+'.mp4 '+foldername+filename+'.mp4')
recording = True
showmenu = 0
if cammode == 'picture':
@@ -1445,7 +1447,8 @@ def main():
if showmenu_settings == True:
showmenu = 1
if onlysound != True:
- camera.stop_recording()
+ #camera.stop_recording()
+ stoprecording(camera, rec_process)
os.system('pkill arecord')
soundlag=starttime-sound_start
db.update('videos', where='filename="'+filmfolder+'.videos/'+video_origins+'.mp4"', soundlag=soundlag)
@@ -4098,7 +4101,23 @@ def stretchaudio(filename,fps):
def encoder():
global bitrate
- return '-c:v h264_omx -profile:v high -level:v 4.2 -preset slow -bsf:v h264_metadata=level=4.2 -g 1 -b:v '+str(bitrate)+' -c:a copy '
+ #return '-c:v h264_omx -profile:v high -level:v 4.2 -preset slow -bsf:v h264_metadata=level=4.2 -g 1 -b:v '+str(bitrate)+' -c:a copy '
+ return '-c:v copy -c:a copy '
+
+def has_audio_track(file_path):
+ try:
+ # Parse the media file
+ media_info = MediaInfo.parse(file_path)
+
+ # Check for audio tracks
+ for track in media_info.tracks:
+ if track.track_type == "Audio":
+ return True
+ return False
+
+ except Exception as e:
+ print(f"Error parsing {file_path}: {e}")
+ return None
#-------------Compile Shot--------------
@@ -4125,6 +4144,11 @@ def compileshot(filename,filmfolder,filmname):
#run_command('ffmpeg -i ' + video_origins + '.h264 -c:v h264_omx -profile:v high -level:v 4.2 -preset slower -bsf:v h264_metadata=level=4.2 -g 1 -b:v '+str(bitrate)+' '+ video_origins + '.mp4')
run_command('ffmpeg -fflags +genpts -r 25 -i ' + video_origins + '.h264 '+encoder()+ video_origins + '.mp4')
os.system('ln -sfr '+video_origins+'.mp4 '+filename+'.mp4')
+ if has_audio_track(filename+'.mp4'):
+ print('cool has audio')
+ else:
+ print('trimming audio')
+ video_origins = (os.path.realpath(filename+'.mp4'))[:-4]
if not os.path.isfile(filename + '.wav'):
audiosilence(filename)
#add audio/video start delay sync
@@ -4318,7 +4342,8 @@ def rendershot(filmfolder, filmname, renderfilename, scene, shot):
scenedir = filmfolder + filmname + '/scene' + str(scene).zfill(3) + '/shot' + str(shot).zfill(3) + '/'
#return if no file
# Video Hash
- if os.path.isfile(renderfilename + '.h264') == True:
+ #if os.path.isfile(renderfilename + '.h264') == True:
+ if has_audio_track(renderfilename+'.mp4') == False:
compileshot(renderfilename,filmfolder,filmname)
audiohash = str(int(countsize(renderfilename + '.wav')))
with open(scenedir + '.audiohash', 'w') as f:
@@ -4642,7 +4667,7 @@ def renderscene(filmfolder, filmname, scene):
audiosize = countsize(renderfilename + '.wav') * 0.453
except:
print('noothing here')
- os.system('mv ' + renderfilename + '.mp4 ' + renderfilename + '_tmp.mp4')
+ #os.system('mv ' + renderfilename + '.mp4 ' + renderfilename + '_tmp.mp4')
if debianversion == 'stretch':
p = Popen(['avconv', '-y', '-i', renderfilename + '.wav', '-acodec', 'libmp3lame', '-ac', '2', '-b:a', '320k', renderfilename + '.mp3'])
else:
@@ -4657,8 +4682,10 @@ def renderscene(filmfolder, filmname, scene):
##MERGE AUDIO & VIDEO
writemessage('Merging audio & video')
#os.remove(renderfilename + '.mp4')
- call(['MP4Box', '-rem', '2', renderfilename + '_tmp.mp4'], shell=False)
- call(['MP4Box', '-add', renderfilename + '_tmp.mp4', '-add', renderfilename + '.mp3', '-new', renderfilename + '.mp4'], shell=False)
+ call(['MP4Box', '-rem', '2', renderfilename + '.mp4'], shell=False)
+ #call(['MP4Box', '-inter', '40', '-v', renderfilename + '_tmp.mp4'], shell=False)
+ call(['MP4Box', '-add', renderfilename + '.mp4', '-add', renderfilename + '.mp3', '-new', renderfilename + '_tmp.mp4'], shell=False)
+ call(['ffmpeg', '-i', renderfilename + '_tmp.mp4', '-r', '25', '-c:v', 'copy', '-c:a', 'copy', '-movflags', 'faststart', renderfilename+'.mp4', '-y'], shell=False)
os.remove(renderfilename + '_tmp.mp4')
os.remove(renderfilename + '.mp3')
else:
@@ -4750,7 +4777,7 @@ def renderfilm(filmfolder, filmname, comp, scene, muxing):
#muxing mp3 layer to mp4 file
#count estimated audio filesize with a bitrate of 320 kb/s
audiosize = countsize(renderfilename + '.wav') * 0.453
- os.system('mv ' + renderfilename + '.mp4 ' + renderfilename + '_tmp.mp4')
+ #os.system('mv ' + renderfilename + '.mp4 ' + renderfilename + '_tmp.mp4')
if debianversion == 'stretch':
p = Popen(['avconv', '-y', '-i', renderfilename + '.wav', '-acodec', 'libmp3lame', '-ac', '2', '-b:a', '320k', renderfilename + '.mp3'])
else:
@@ -4765,9 +4792,10 @@ def renderfilm(filmfolder, filmname, comp, scene, muxing):
##MERGE AUDIO & VIDEO
writemessage('Merging audio & video')
#os.remove(renderfilename + '.mp4')
- call(['MP4Box', '-rem', '2', renderfilename + '_tmp.mp4'], shell=False)
- call(['MP4Box', '-add', renderfilename + '_tmp.mp4', '-add', renderfilename + '.mp3', '-new', renderfilename + '.mp4'], shell=False)
- #call(['MP4Box', '-inter', '500', renderfilename + '.mp4'], shell=False)
+ call(['MP4Box', '-rem', '2', renderfilename + '.mp4'], shell=False)
+ #call(['MP4Box', '-inter', '40', '-v', renderfilename + '_tmp.mp4'], shell=False)
+ call(['ffmpeg', '-i', renderfilename + '_tmp.mp4', '-c', 'copy', '-movflags', 'faststart', renderfilename+'.mp4', '-y'], shell=False)
+ call(['MP4Box', '-add', renderfilename + '.mp4', '-add', renderfilename + '.mp3', '-new', renderfilename + '_tmp.mp4'], shell=False)
os.remove(renderfilename + '_tmp.mp4')
os.remove(renderfilename + '.mp3')
else:
@@ -5837,6 +5865,21 @@ def stopstream(camera, stream):
stream = ''
return stream
+def startrecording(camera, takename):
+ global bitrate, quality, profilelevel
+ # FFmpeg command to take H.264 input from stdin and output to MP4
+ ffmpeg_cmd = ['ffmpeg','-i', 'pipe:0', '-fflags', '+genpts', '-c:v', 'copy', '-movflags', 'frag_keyframe+empty_moov', '-bsf:v', 'dump_extra', '-b:v', str(bitrate), '-level:v', '4.2', '-g', '1', '-r', '25', '-f', 'mp4', takename, '-loglevel','debug', '-y']
+ rec_process = subprocess.Popen(ffmpeg_cmd, stdin=subprocess.PIPE)
+ camera.start_recording(rec_process.stdin, format='h264', bitrate = bitrate, level=profilelevel, quality=quality, intra_period=1)
+ return rec_process
+
+def stoprecording(camera, rec_process):
+ camera.stop_recording()
+ # Close the FFmpeg process
+ rec_process.stdin.close()
+ rec_process.wait()
+ print("Recording complete!")
+
#-------------Beeps-------------------
def beep(bus):
diff --git a/install.sh b/install.sh
@@ -53,7 +53,7 @@ apt-get update
apt-get upgrade -y
if [ "$version" = "buster" ]
then
- apt-get -y install git python3-pip python-configparser ffmpeg mediainfo gpac omxplayer sox cpufrequtils apache2 libapache2-mod-wsgi-py3 libdbus-glib-1-dev dbus libdbus-1-dev usbmount python3-numpy python3-pil python3-smbus python3-shortuuid wiringpi make gcc cmake pmount python3-ifaddr python3-pygame python3-serial
+ apt-get -y install git python3-pip python-configparser ffmpeg mediainfo gpac omxplayer sox cpufrequtils apache2 libapache2-mod-wsgi-py3 libdbus-glib-1-dev dbus libdbus-1-dev usbmount python3-numpy python3-pil python3-smbus python3-shortuuid wiringpi make gcc cmake pmount python3-ifaddr python3-pygame python3-serial, libmediainfo-dev, python3-pymediainfo
else
apt-get -y install git python3-pip python-configparser libav-tools mediainfo gpac omxplayer sox cpufrequtils apache2 libapache2-mod-wsgi-py3 libdbus-glib-1-dev dbus libdbus-1-dev usbmount python3-numpy python3-pil python3-smbus python3-shortuuid wiringpi make gcc cmake python3-ifaddr python3-pygame python3-serial
fi