Notifications
Clear all

MP4 video camera?

62 Posts
6 Users
16 Likes
4,856 Views
byron
(@byron)
No Title
Joined: 5 years ago
Posts: 1122
 
Posted by: @robo-pi

Actually, that's probably the best way to always write comments.  You should always try to write comments as if you are explaining what you are doing to someone else who might not know.  Think of how easy that's going to be for you to read when you come back to your own code much later. 👍 

Yes, too true.  I must do better as I've annoyed myself a few times resolving some issues I worked out the answer for a year or so back, but now memory fades and I have to work it all out again 🤨

I don't know if this will work, but I'll give it a shot.  I took a small video of my small pi screen (though not as small as the one you are using for your project, so this probably not much use at all).  This video show a small tKinter created GUI coded with the picamera module. The GUI initiates a small camera preview window (you can see both the GUI and the preview on the same screen) and has buttons to start and stop a recording,  and has options to play with various video settings.  So I clicked on record and recorded the pi window showing the gui buttons and the preview window in use whilst making a recording of the screen.

Oh dear, it does not work, I get a message that .h264 files are not allowed.  A career in youtubing dies a death on its first attempt. 😐  So now I going to be embarrassed to show the small and very sadly uncommented code snipped so you can give it a go if interested.  This is not a proper program and is just created from some info I garnered from a few web sources and put in my snippets file for some future project.  However it does the use the picamera module without needing to shell out to use the operating system to send commands to the camera, and eliminated all worries about threading or multiprocessing.  Of course this was using a rpi camera.  I'll be picking this project up soon (well I'm talking months)  as my ip camera that focuses on my front gate is on its way out and I'm thinking of replacing it with a rpi camera that peers through a window so its not ravaged by the weather. (and its cheap 😎 )

Posted by: @robo-pi

All I know is that it works. 😎  Whether it's the proper way to do things I have clue. 😮

Well thats my philosophy too.  So by no means am I thinking you should change any of your code as its a good working solution.  But I though it may be of interest for some future project as along your development path I think you were having issues with getting a small preview screen to work with picamera, and had tKinter locking issues when shelling out to the operation system.

#!/usr/bin/python

import tkinter as tk

import picamera

from time import sleep

 

rec_no = 1

 

camera = picamera.PiCamera()

choices = ['off', 'auto', 'sunlight', 'cloudy', 'shade',

           'tungsten', 'fluorescent', 'incandescent', 'flash', 'horizon']

effects = ['none', 'negative', 'solarize', 'sketch', 'denoise', 'emboss', 'oilpaint', 'hatch', 'gpen', 'pastel', 'watercolor', 'film',

           'blur', 'saturation', 'colorswap', 'washedout', 'posterise', 'colorpoint', 'colorbalance', 'cartoon', 'deinterlace1', 'deinterlace2']

 

 

def CameraON():

    camera.preview_fullscreen = False

    camera.preview_window = (90, 100, 320, 640)

    camera.resolution = (640, 480)

    camera.start_preview()

 

def VideoStart():

    global rec_no

    #camera.start_preview()

    camera.start_recording('/home/pi/Desktop/video'+str(rec_no)+'.h264')    

 

def VideoStop():

    global rec_no

    camera.stop_recording()

    rec_no +=1

    #camera.stop_preview()

    

def CameraOFF():

    camera.stop_preview()

 

 

def EXIT():

    root.destroy

    camera.stop_preview()

    camera.close()

    quit()

 

 

def UpdateBrightness(value):

    camera.brightness = int(value)

 

 

def UpdateContrast(value):

    camera.contrast = int(value)

 

 

def UpdateSharpness(value):

    camera.sharpness = int(value)

 

 

def UpdateSaturation(value):

    camera.saturation = int(value)

 

 

def SetAWB(var):

    camera.awb_mode = var

 

 

def SetEFFECTS(var):

    camera.image_effect = var

 

 

def Zoom(var):

    x = float("0."+var)

    camera.zoom = (0.5, 0.5, x, x)

 

 

root = tk.Tk()

root.resizable(width=False, height=False)

root.geometry("520x300")

root.title("tKinter and picamera")

 

root.buttonframe = tk.Frame(root)

root.buttonframe.grid(row=5, column=3, columnspan=2)

 

tk.Button(root.buttonframe, text='Start Camera',

          command=CameraON).grid(row=1, column=1)

tk.Button(root.buttonframe, text='StartVideo',

          command=VideoStart).grid(row=1, column=2)

tk.Button(root.buttonframe, text='StopVideo',

          command=VideoStop).grid(row=1, column=3)

tk.Button(root.buttonframe, text='Kill Camera',

          command=CameraOFF).grid(row=1, column=4)

tk.Button(root.buttonframe, text='Exit',

          command=EXIT).grid(row=1, column=5)

 

 

tk.Scale(root.buttonframe, from_=30, to=100, orient=tk.HORIZONTAL,

         label="Brightness", command=UpdateBrightness).grid(row=2, column=1)

tk.Scale(root.buttonframe, from_=-100, to=100, orient=tk.HORIZONTAL,

         label="Contrast", command=UpdateContrast).grid(row=2, column=2)

tk.Scale(root.buttonframe, from_=-100, to=100, orient=tk.HORIZONTAL,

         label="Sharpness", command=UpdateSharpness).grid(row=2, column=3)

tk.Scale(root.buttonframe, from_=-100, to=100, orient=tk.HORIZONTAL,

         label="Saturation", command=UpdateSaturation).grid(row=2, column=4)

tk.Scale(root.buttonframe, from_=10, to=99, orient=tk.HORIZONTAL,

         label="Zoom", command=Zoom).grid(row=2, column=5)

 

AWB_Var = tk.StringVar(root)

AWB_Var.set(choices[1])

AWB_Option = tk.OptionMenu(root.buttonframe, AWB_Var,

                           *choices, command=SetAWB).grid(row=3, column=2)

 

EFFECT_Var = tk.StringVar(root)

EFFECT_Var.set(effects[0])

EFFECT_Option = tk.OptionMenu(

    root.buttonframe, EFFECT_Var, *effects, command=SetEFFECTS).grid(row=3, column=3)

 

#enable next line to lock window in place

#root.overrideredirect(True)

 

root.mainloop()

This post was modified 3 years ago by byron

   
ReplyQuote
Robo Pi
(@robo-pi)
Robotics Engineer
Joined: 5 years ago
Posts: 1669
Topic starter  

@byron

Your code doesn't really need comments as you've chosen very informative names for all your methods and variables.   It's very clean code. 👍 

I'll have to go back and look at using Picamera again.  I don't even remember what the problem was before.  But for some reason I was having a problem with Picamera so that's why I went with raspivid.

Posted by: @byron

Oh dear, it does not work, I get a message that .h264 files are not allowed.

I found .h264 files to be incompatible with other programs and resources too.  That's why I installed gpac or MP4Box and convert them to mp4.   Mp4 seems to be compatible with a lot more programs and resources, including my video editing software.

Nice coding example. 👍  Thanks for sharing. 🥂 

DroneBot Workshop Robotics Engineer
James


   
ReplyQuote
(@dronebot-workshop)
Workshop Guru Admin
Joined: 5 years ago
Posts: 1081
 
Posted by: @byron

Oh dear, it does not work, I get a message that .h264 files are not allowed.  A career in youtubing dies a death on its first attempt

Are you trying to upload to YouTube or attach a file to your forum post, Byron?  Obviously, I have no control over YouTube, but if it's the forum you were blocked from I can probably fix that.  Just let me know.

😎

Bill

"Never trust a computer you can’t throw out a window." — Steve Wozniak


   
ReplyQuote
byron
(@byron)
No Title
Joined: 5 years ago
Posts: 1122
 

@dronebot-workshop

Hi Bill, I was trying to upload it to this forum.  My YouTube comment was a bit tongue in cheek.   I may experiment in loading up a video to YouTube at some point in time just to see whats involved, but nothing serious.  However I see that @robo-pi mentions converting his .h264 with gpac to mp4v so I will see if I can do the same and see it thats a better route to uploading video to this forum rather than putting you to any trouble to get the upload of .h264 working.

Thanks for suggesting you could look into this.  And as its getting real close now, and I've been allowed to raid the Christmas goodies shelf for some munchies, I take this opportunity to wish you a happy Christmas time and thanks for your videos that helped a lot in passing the 'lockdown' time pleasantly enough.  BTW I expect you have seen that adafuit have produced their xiao equivalent -SAMD21 Dev Board with STEMMA QT.  Not a cheap as the xiao of course but still only $5 ish and it has an easy i2c connection port and a reset button on board which would have been jolly useful on the xiao. 😎 


   
ReplyQuote
(@dronebot-workshop)
Workshop Guru Admin
Joined: 5 years ago
Posts: 1081
 
Posted by: @byron

 However I see that @robo-pi mentions converting his .h264 with gpac to mp4v so I will see if I can do the same and see it thats a better route to uploading video to this forum rather than putting you to any trouble to get the upload of .h264 working.

If you check out the video I did recently on Raspberry Pi Cameras you'll see the method of converting .h264 files, which I'm sure is the same method our resident poet is using.

Actually, I checked and currently, the forum blocks ALL types of video files in its "anti-spam" settings.  I don't think literally considers all videos to be spam, I expect that the concern is the potential SIZE of the video files.  So at the moment, you will have issues with your MP4 file as well.

The video I'm releasing tomorrow on YouTube is a 17.8 GB MP4 file, uploading something like that to the forum would probably crash it (although I believe the forum also blocks any attachment over 10MB).

Your best bet is to actually upload it to YouTube and then paste the YouTube URL into the forum. You could make it unlisted if you wish.

😎

Bill

"Never trust a computer you can’t throw out a window." — Steve Wozniak


   
ReplyQuote
(@dronebot-workshop)
Workshop Guru Admin
Joined: 5 years ago
Posts: 1081
 
Posted by: @byron

BTW I expect you have seen that adafuit have produced their xiao equivalent -SAMD21 Dev Board with STEMMA QT.  Not a cheap as the xiao of course but still only $5 ish and it has an easy i2c connection port and a reset button on board which would have been jolly useful on the xiao. 😎 

I have already purchased 5 of them last week LOL!

😎

Bill

"Never trust a computer you can’t throw out a window." — Steve Wozniak


   
ReplyQuote
frogandtoad
(@frogandtoad)
Member
Joined: 5 years ago
Posts: 1458
 

@robo-pi, @codecage

So how did you go gent's?

Were you able to replicate the problem I highlighted, and try the alternative code using threading?


   
ReplyQuote
codecage
(@codecage)
Member Admin
Joined: 5 years ago
Posts: 1037
 

@frogandtoad

Been busy with other endeavors and haven't been doing anything with @robo-pi video camera setup.

SteveG


   
ReplyQuote
Robo Pi
(@robo-pi)
Robotics Engineer
Joined: 5 years ago
Posts: 1669
Topic starter  
Posted by: @frogandtoad

@robo-pi, @codecage

So how did you go gent's?

Were you able to replicate the problem I highlighted, and try the alternative code using threading?

I was not able to replicate the problem you were having.   I only ever get one instance of the Tkinter window running.  You said that you were experiencing multiple instances of the Tkinter window???

From what I've been studying about multiprocessing, using process would be the preferred way to go for what I'm doing.  Raspivid is a totally separate process from the Tkinter window.  Therefore running it as in individual process that has its own memory space would be the preferred method as far as I can see.

Perhaps I'm not understanding the problem you are having?  So far my program is doing precisely as I expect that it would.   So I'm not seeing any problems at my end.  Am I missing something?

 

DroneBot Workshop Robotics Engineer
James


   
ReplyQuote
frogandtoad
(@frogandtoad)
Member
Joined: 5 years ago
Posts: 1458
 

@codecage

Ok, thanks... interested to know what you get once you try it out.


   
ReplyQuote
frogandtoad
(@frogandtoad)
Member
Joined: 5 years ago
Posts: 1458
 

@robo-pi

Posted by: @robo-pi

I was not able to replicate the problem you were having.   I only ever get one instance of the Tkinter window running.  You said that you were experiencing multiple instances of the Tkinter window???

Hmmm, that's very interesting... did you try to drag the GUI out of the way with your mouse after clicking the record button as I suggested?  I just want to be sure, because I am indeed having a new GUI created when I click the record button, and then again on the newly created GUI, but it does not happen when I change it to the threading model.

Posted by: @robo-pi

From what I've been studying about multiprocessing, using process would be the preferred way to go for what I'm doing.

Ok, it's been a while for me, so that's a research topic for me then, to make sure I haven't been leading people down the wrong path.

Posted by: @robo-pi

Perhaps I'm not understanding the problem you are having?  So far my program is doing precisely as I expect that it would.   So I'm not seeing any problems at my end.  Am I missing something?

I'm surprised you're not getting the same results as I described.  I am running the code under windows however, but I don't see how that should make a difference?  What I'll do, is set up a test on one of my Linux virtual machines as see if I can replicate it there as well, and let you all know how it goes.


   
ReplyQuote
Robo Pi
(@robo-pi)
Robotics Engineer
Joined: 5 years ago
Posts: 1669
Topic starter  
Posted by: @frogandtoad

Hmmm, that's very interesting... did you try to drag the GUI out of the way with your mouse after clicking the record button as I suggested?  I just want to be sure, because I am indeed having a new GUI created when I click the record button, and then again on the newly created GUI, but it does not happen when I change it to the threading model.

Yes, I dragged it away.  I also looked in the task bar to see if a second instance was running and there was none.  So I'm not experiencing this phenomena. 

Posted by: @frogandtoad

Ok, it's been a while for me, so that's a research topic for me then, to make sure I haven't been leading people down the wrong path.

Well, as I've said before, I no expert on multiprocessing myself.   But from what I've read it appears to me that when you want to run a separate process that's exactly what the process function is designed to do.  Plus, when I kill raspivid I use pkill on the command line.  That command actually stands for "process kill".

So it seems to me that even if you did run it as a thread, the OS is still going to be treating it as a separate process anyway.  Otherwise how could it kill it using pkill?

Posted by: @frogandtoad

I'm surprised you're not getting the same results as I described.  I am running the code under windows however, but I don't see how that should make a difference?  What I'll do, is set up a test on one of my Linux virtual machines as see if I can replicate it there as well, and let you all know how it goes.

Ok, that's probably the reason we're getting different results.   I'm running it on Raspbian on a Raspberry Pi. 

Apparently Windows is doing things differently.  That certainly explains why we're getting different results.

Even so, it doesn't make a lot of sense to me why even Windows should launch an entire new copy of the Tkinter program just to run raspivid as a separate process.

If I find time I can try to run the program on my Windows machine and see if I get the same results.  Not sure when I'll be able to do that.  I'm suffering in great pain right now from a strange new disease called Covid-19.  It's not fun trying to do anything with all this pain.  I spend the vast majority of my time lately laying in bed moaning in agony.  The people who say you don't want to get this are right on!

DroneBot Workshop Robotics Engineer
James


   
ReplyQuote
frogandtoad
(@frogandtoad)
Member
Joined: 5 years ago
Posts: 1458
 

@robo-pi

Posted by: @robo-pi

Yes, I dragged it away.  I also looked in the task bar to see if a second instance was running and there was none.  So I'm not experiencing this phenomena. 

Ok, thanks for trying it... I will also try it out on my Linux machine and let you know the results.

Posted by: @frogandtoad
Posted by: @frogandtoad

Ok, it's been a while for me, so that's a research topic for me then, to make sure I haven't been leading people down the wrong path.

Well, as I've said before, I no expert on multiprocessing myself.   But from what I've read it appears to me that when you want to run a separate process that's exactly what the process function is designed to do.  Plus, when I kill raspivid I use pkill on the command line.  That command actually stands for "process kill".

So it seems to me that even if you did run it as a thread, the OS is still going to be treating it as a separate process anyway.  Otherwise how could it kill it using pkill?

Yes, a when you want a separate process, calling process will give it to you, but it will also give you a brand new python interpreter along with it, as a process is actually a new program instance, with it's own memory and variables, and all without a relationship to any new process.  The GUI program launched by the python interpreter is represented as a process just like any other program, and many threads run within that one single process when using the threading model.

I put together a simple piece of test code as follows, and this code on windows produces a new GUI at each click (I haven't tested it on Linux yet, but I will later tonight) - Just comment out the process line and uncomment the threading line to test for both scenario's:

from tkinter import *
import threading
from multiprocessing import Process

def runAsNewProcess():
    pass

def createProcess():
    #p = threading.Thread(target=runAsNewProcess)
    p = Process(target=runAsNewProcess)
    p.start()

root = Tk()

button = Button(root, text="Click to Create New GUI"command=createProcess)
button.pack()

root.mainloop()

Very simple program, and no reason for it to work differently on either O/S, but we'll find out after testing.

Posted by: @robo-pi

Ok, that's probably the reason we're getting different results.   I'm running it on Raspbian on a Raspberry Pi. 

Apparently Windows is doing things differently.  That certainly explains why we're getting different results.

Even so, it doesn't make a lot of sense to me why even Windows should launch an entire new copy of the Tkinter program just to run raspivid as a separate process.

Windows should not be doing it any differently, but according to your results it appears to be doing just that - will know more after testing.

Posted by: @robo-pi

If I find time I can try to run the program on my Windows machine and see if I get the same results.  Not sure when I'll be able to do that.  I'm suffering in great pain right now from a strange new disease called Covid-19.  It's not fun trying to do anything with all this pain.  I spend the vast majority of my time lately laying in bed moaning in agony.  The people who say you don't want to get this are right on!

Sorry to hear that.
Get plenty of rest, and hope you get better soon.


   
ReplyQuote
Robo Pi
(@robo-pi)
Robotics Engineer
Joined: 5 years ago
Posts: 1669
Topic starter  
Posted by: @frogandtoad

Yes, a when you want a separate process, calling process will give it to you, but it will also give you a brand new python interpreter along with it, as a process is actually a new program instance

But raspivid isn't a Python program, so it doesn't require a Python interpreter.  I think I see the problem.  I actually suspected this when I first wrote the program, but since the program was working for me I didn't see it as being a problem.

 

Posted by: @frogandtoad

def runAsNewProcess():
    pass

def createProcess():
    #p = threading.Thread(target=runAsNewProcess)
    p = Process(target=runAsNewProcess)
    p.start()

In the above code the "process" you are creating is actually a python method named runAsNewProcess()

So it makes sense that the system would see this as wanting to create a new Python process that runs this specific Python method code.

So to avoid this the new process should be called directly instead of calling a Python method as follows:

 

def runAsNewProcess():
    pass

def createProcess():

    command = "terminal command to launch raspivid"
    p = Process(target=subprocess.call((command), shell=True))
    p.start()

By doing it this way, the new process should be raspivid directly, no Python methods involved.

~~~~

I'm not sure if this will actually work, but it should.  I just now looked up online and have seen some example where target is pointing directly to a subprocess instead of to a Python method.

The problem occurs when placing the subprocess.call command inside a Python method because then the process command thinks the Python method is what you want to run as a separate process since that is the target of the process call.

So the solution should be to just call raspivid directly from the process statement instead of calling it through a Python method.

I would think this should work, but I'm in no shape here to try it right now.  It was all I could do to post this reply.

DroneBot Workshop Robotics Engineer
James


   
ReplyQuote
Robo Pi
(@robo-pi)
Robotics Engineer
Joined: 5 years ago
Posts: 1669
Topic starter  

By  the way, the reason is works with threading is because you are creating a new thread to run the method runAsNewProcess().

Then that new thread launches raspivid and just "hangs up" until raspivid has been terminated.  Only then is control returned to the runAsNewProcess() method which then quits.

So it will certainly work that way.  But if you can run raspivid directly as a separate process that would probably be better.  Then you don't have the unneeded Python method thread just hanging there the whole time raspivid is recording a video.

 

DroneBot Workshop Robotics Engineer
James


   
ReplyQuote
Page 4 / 5