Page 1 of 2 12 LastLast
Results 1 to 40 of 49

Thread: VB.NET - MPEG-4 Screen recorder. May 23rd, 2015 update

  1. #1

    Thread Starter
    Fanatic Member Peter Porter's Avatar
    Join Date
    Jul 2013
    Posts
    532

    VB.NET - MPEG-4 Screen recorder. May 23rd, 2015 update

    Created with Visual Basic 2010, using FFmpeg to compile captured images & audio to an MPEG-4 video. It's not perect, but when I have the time, I 'll tweak it some more.

    Name:  Cap2Vid.png
Views: 9749
Size:  29.0 KB

    * Adjusts frames per second (fps) and capture interval according to screen resolution's total pixels. Screen resolutions with a pixel total equal to or less than 921600 (1280x720) are captured at 30fps. Larger pixel totals (1280x1024, 1920x1080, etc...) are captured at 25fps.

    * The "Crop to 16.9" checkbox is only visible if your screen resolution is not 16.9 aspect ratio.

    * If "Record Mouse" is checked, along with "Crop to 16.9", the capture region follows the mouse according to actual screen bounds height.

    * Creates a Folder called "Captured", which is placed in Window's system's "My Videos" folder.

    * Extracts FFmpeg from resources and places it in the captured folder. FFmpeg, with dshow, captures audio from the speakers and saves it as an mp3 file, while merging captured images to a temporary mp4. Clicking "Stop" restarts FFmpeg to merge both to a dated mp4 in the captured folder.

    * All captured videos are given unique Date & Time filenames.

    The code had to be reposted since I exceeded the character limit here. You can find it below this thread, posts labeled May 23rd, part 1 thru 4.

    Important:
    For this project to work, you need to download either the 32bit or 64bit FFmpeg static builds, which needs to be added to this project's resources. The direct links above to the ffmpeg static build downloads for Windows are from it's parent site, Zeranoe FFmpeg. They are older versions, but work fine compared to the latest version which is buggy.

    Your system's Stereo Mix has to be enabled in order for this app to record sound.

    Enabling Stereo Mix for Windows Vista, 7 and 8
    * Right-click over the Speaker icon by the system clock then choose Recording Devices to open the Recording tab of "Sound".
    * Right-click Stereo Mix, and from it's dropdown menu, click Enable.

    Note (Vista, 7 and 8):
    If you don't see Stereo Mix, right click within the Recording tab window, then check "Show Disabled Devices".

    Enabling Stereo Mix for Windows XP
    * Click the Speaker icon by the system clock.
    * In the window that appears, choose Options then Properties.
    * In the next window, click the "Recording" radio button, then in "Show the following volume controls", click in the box for Stereo Mix, then "OK".


    This project's zip is clean of binaries, but it only works on 64bit systems.
    You can easily change it to 32bit in VB's Configuration Manager.


    Don't forget to add FFmpeg static build (32bit or 64bit) to this project's resources.
    Attached Files Attached Files
    Last edited by Peter Porter; Aug 27th, 2015 at 08:20 AM.

  2. #2
    PowerPoster Nightwalker83's Avatar
    Join Date
    Dec 2001
    Location
    Adelaide, Australia
    Posts
    13,344

    Re: VB.NET - Fixed! Screen Recorder, capture fullscreen with audio

    Maybe you should attach the project to the first post? I for one would have difficulty whether something is 98 pixels away from something else.
    when you quote a post could you please do it via the "Reply With Quote" button or if it multiple post click the "''+" button then "Reply With Quote" button.
    If this thread is finished with please mark it "Resolved" by selecting "Mark thread resolved" from the "Thread tools" drop-down menu.
    https://get.cryptobrowser.site/30/4111672

  3. #3

    Thread Starter
    Fanatic Member Peter Porter's Avatar
    Join Date
    Jul 2013
    Posts
    532

    VB.NET - Project file attached to 1st post for Screen Recorder

    Hi Nightwalker83

    I've attached a working project file to my first post. The code and project file above was extracted from the main body of my application which is why it doesn't look great, but it works. I'll gradually add more features as I clean-up my main application's code.

    Everything works, except for the fact that the VB Timer is way off. Wish I knew a way to incorporate a High Resolution Timer.

  4. #4

    Thread Starter
    Fanatic Member Peter Porter's Avatar
    Join Date
    Jul 2013
    Posts
    532

    Solved the interval problem for better frames per second.

    Ok... I thought of a way of capturing more frames per second. The save function needs to be placed in two backgroundworkers called from the VidRec timer. The VidRec timer will call a save from the first backgroundworker, then configure itself to call the next save from the second backgroundworker, then back again. One backgroundworker will be saving images with odd numbers, and the other even, this way all saved images from both backgroundworkers can be played together in a picturebox.

    I'll even test the capture function within a backgroundworker to see if it's faster than a timer. Maybe split this function between 2 or 3 backgroundworkers.

    As soon as this project is updated, I'll repost the source code as well as a new dated zip file.

  5. #5
    New Member
    Join Date
    Aug 2009
    Posts
    8

    Lightbulb Re: Solved the interval problem for better frames per second.

    Quote Originally Posted by Peter Porter View Post
    Ok... I thought of a way of capturing more frames per second. The save function needs to be placed in two backgroundworkers called from the VidRec timer. The VidRec timer will call a save from the first backgroundworker, then configure itself to call the next save from the second backgroundworker, then back again. One backgroundworker will be saving images with odd numbers, and the other even, this way all saved images from both backgroundworkers can be played together in a picturebox.

    I'll even test the capture function within a backgroundworker to see if it's faster than a timer. Maybe split this function between 2 or 3 backgroundworkers.

    As soon as this project is updated, I'll repost the source code as well as a new dated zip file.
    Hi Peter, sorry to bump into this old thread but am working on a similar tool and was wondering whether you were able to implment the above and get some decent improvement? I couldnt find a newer post with an updated version...so thought to ask..
    Currently I am able to generate screenshots and even capture the audio seperately. I can combine them using ffmpeg but I find that the audio/video is out of sync (video lags in coparison to audio) . This might be because my application is not able to produce correct number of screenshots(though i have set video timer to 10). I plan to use the backgroundworker method. Could you please share the updated code please?

  6. #6

    Thread Starter
    Fanatic Member Peter Porter's Avatar
    Join Date
    Jul 2013
    Posts
    532

    Re: VB.NET - Screen recorder with audio. Zip file and screenshots

    Hi Sunny,

    I have an older version of this program that captures at the correct interval... well it's a bit over the number of frames it should be capturing, which is an easy fix by deleting the few duplicate frames it captures by knowing when this occurs, that's if you can figure out how to prevent it from crashing. It crashes after 600 to 700 frames. When it crashes, you can't save the images. Haven't had time to correct this, which is why I made the updated version attached above which is great for capturing tutorials, then you would have to use some video editing software to sync the audio with it. Could also be done with ffmpeg.

    With the above attached version, the saving of each frame slows it down. Worse when you try to capture a video. As soon as I can dig up the old version, I'll attach it to this post. Maybe you can fix it.

  7. #7

    Thread Starter
    Fanatic Member Peter Porter's Avatar
    Join Date
    Jul 2013
    Posts
    532

    Re: VB.NET - Screen Recorder with Audio. Update 22 Dec 13

    Updated the Screen Recorder. It now captures at 30fps while recording audio.

  8. #8
    New Member
    Join Date
    Aug 2009
    Posts
    8

    Re: VB.NET - Screen Recorder with Audio. Update 22 Dec 13

    Quote Originally Posted by Peter Porter View Post
    Updated the Screen Recorder. It now captures at 30fps while recording audio.
    Thanks peter. However the code in the zip file you provided doesnt open up in my Visual Basic 2008... Could you explain in short the logic as to how to achieved to capture frames at such high fps?

    My code cant capture more than 9-10 fps

  9. #9

    Thread Starter
    Fanatic Member Peter Porter's Avatar
    Join Date
    Jul 2013
    Posts
    532

    Re: VB.NET - Screen Recorder with Audio. Update 22 Dec 13

    Hi sunnydsouza,

    I attached some code to this post, but it's been updated as well as the zipped files in 32bit and 64bit versions. My Screen Recorder now converts straight to MPEG-4 video. Hopefully the code above works for your version of Visual basic. Just one thing, Vidrec, Player and AudioRec are Timers. I haven't updated the player yet, so it will only play audio for now.

  10. #10
    New Member
    Join Date
    Aug 2009
    Posts
    8

    Re: VB.NET - Screen Recorder with Audio. Update 22 Dec 13

    Quote Originally Posted by Peter Porter View Post
    Hi sunnydsouza,

    I attached some code to this post, but it's been updated as well as the zipped files in 32bit and 64bit versions. My Screen Recorder now converts straight to MPEG-4 video. Hopefully the code above works for your version of Visual basic. Just one thing, Vidrec, Player and AudioRec are Timers. I haven't updated the player yet, so it will only play audio for now.
    Thanks a lot Peter. I will check this out. Just out of curiosity - Does the video created by ffmpeg capture the audio also with it? And if so, are they both in sync?

    Thanks a lot again.

  11. #11

    Thread Starter
    Fanatic Member Peter Porter's Avatar
    Join Date
    Jul 2013
    Posts
    532

    Re: VB.NET - Screen Recorder with Audio. Update 22 Dec 13

    It doesn't merge audio with video yet, but I'll have that fixed soon.

    I've updated the code again so the video and audio are saved in the same folder called Captured which this program creates in the MyVideos or Videos folder.

  12. #12

    Thread Starter
    Fanatic Member Peter Porter's Avatar
    Join Date
    Jul 2013
    Posts
    532

    Re: VB.NET - Screen Recorder with Audio. Update 22 Dec 13

    It doesn't merge audio with video yet, but I'll have that fixed soon.

    I've updated the code again so the video and audio are saved in the same folder called Captured which this program creates in the MyVideos or Videos folder.

  13. #13
    PowerPoster Nightwalker83's Avatar
    Join Date
    Dec 2001
    Location
    Adelaide, Australia
    Posts
    13,344

    Re: VB.NET - Screen Recorder with audio. Converts to MPEG-4 video now. Update 29 Dec

    Is it possible to add an option to capture the mouse cursor to?
    when you quote a post could you please do it via the "Reply With Quote" button or if it multiple post click the "''+" button then "Reply With Quote" button.
    If this thread is finished with please mark it "Resolved" by selecting "Mark thread resolved" from the "Thread tools" drop-down menu.
    https://get.cryptobrowser.site/30/4111672

  14. #14
    New Member
    Join Date
    Mar 2013
    Posts
    1

    Re: VB.NET - Screen Recorder with audio. Converts to MPEG-4 video now. Update 29 Dec

    Awesome but i have one more question and that's - how to change the video codec (e.g for 3gp, avi, wmv, mkv) ?

  15. #15
    New Member
    Join Date
    Jun 2014
    Posts
    2

    Re: VB.NET - Screen Recorder with audio. Converts to MPEG-4 video now. Update 29 Dec

    Hi Peter,

    I use your code (64 bit. Because My OS is 64 bit). I can Record Screen Activities when I click stop button. But, I'm recording about 2 minutes but recorded file (test.mp4) is about 22 second. It's very fast.
    I just want to record video. I don't have record audio. By the way, the recorded file size haven't very big. It must be small.

    This is my convert code line.

    proc.StartInfo.Arguments = "-f image2pipe -i pipe:.bmp -pix_fmt yuv420p -vcodec libx264 -r 25 -bufsize 3000k -b:v 2600k -y " + s + "\Captured\test.mp4"

    This is VidREC_Tick Sub:

    Dim writer As New BinaryWriter(proc.StandardInput.BaseStream)

    Frames = Format(fcounter, "000000")
    Label3.Text = Frames

    fcounter = fcounter + 1

    Dim BMP As New System.Drawing.Bitmap(MonitorWidth, MonitorHeight)
    Dim Cap As System.Drawing.Graphics = System.Drawing.Graphics.FromImage(BMP)
    Cap.CopyFromScreen(New Point(0, 0), New Point(0, 0), ScreenSize)
    BMP.Save(writer.BaseStream, System.Drawing.Imaging.ImageFormat.Bmp)

    Label3.Text = Convert.ToString(Frames)

    If Label1.Text = "stop" Then
    VidREC.Enabled = False
    ComboBox1.SelectedIndex = 2
    writer.Close()

    End If
    BMP.Dispose()
    Cap.Dispose()

    GC.Collect()


    How can I set time of original record between time of recorded video?(Duration)

    Thanks.
    Emrah

  16. #16

    Thread Starter
    Fanatic Member Peter Porter's Avatar
    Join Date
    Jul 2013
    Posts
    532

    Re: VB.NET - Screen Recorder with audio. Converts to MPEG-4 video now. Update 29 Dec

    Sorry for the wait, mrhydn, Nightwalker83, ankan. I have another version of my screen recorder that merges audio with the video. I created back in January before I dropped this project. The video plays back slow, or sometimes the frame rate fluctuates, so it's not in sync. The audio might be 5 minutes long, but the video might end up being over 5 minutes, or just a little under. I'll attach an update soon.
    Last edited by Peter Porter; Jun 25th, 2014 at 08:32 AM.

  17. #17
    VB For Fun Edgemeal's Avatar
    Join Date
    Sep 2006
    Location
    WindowFromPoint
    Posts
    4,255

    Re: VB.NET - Screen Recorder with audio. Converts to MPEG-4 video now. Update 29 Dec

    Quote Originally Posted by Peter Porter View Post
    I thought I corrected the frame rate. Maybe it runs fast depending on the system. Works great on my pc. When I have time I'll look over my program again.
    First of all thanks for sharing!

    I would love to see a fix for the playback speed, I've tried all sorts of command line options for ffmpeg but the output file was always playing about 2x faster then the real capture time.

    EDIT UPDATE

    I changed my experiment code again, capture at lower FPS, (still a lot of junk in this, bunch of DoEvents,etc..)
    This captures the mouse pointer and draws a red circle around the mouse pointer when left mouse button is down.
    Attached Files Attached Files
    Last edited by Edgemeal; Sep 28th, 2014 at 09:52 PM.

  18. #18
    Frenzied Member
    Join Date
    Jul 2011
    Location
    UK
    Posts
    1,335

    Re: VB.NET - Screen Recorder with audio. Converts to MPEG-4 video now. Update 29 Dec

    @Edgemeal: Nice work on the screen grab code.

    From your timings, it looks like you are hoping for 75 fps (13.33ms timing loops). Might be a tad optimistic? The best I can achieve is about 18 fps for a screen grab and stream to FFmpeg process with a screen resolution of 1920 x 1080.

    I think half the problem stems from the fps values, both those expected and those that are passed as settings to FFmpeg.

    For example, let's say I was specifying 30 fps for the video playback rate in the call to FFmpeg
    Code:
    proc.StartInfo.Arguments = "-f image2pipe -i pipe:.bmp -pix_fmt yuv420p -c:v libx264 -an -r 30 -bufsize 60000k -b:v 1800k -y -threads 2 " & CaptureDir & "test.mp4"
    but I was only able to grab screencaps at 15fps. Then that would account for the doubling in speed on playback.

    You might think the obvious solution would be to cap the screen grab rate at a value that your hardware can handle, and set the playback rate via FFmpeg to the same value. That would be too easy .

    I capped the grab rate to 12.5 fps (timing loop = 80ms) and passed -r 12.5 to FFmpeg. After recording for 60 seconds, the code had grabbed 737 frames (should have been 750; the grab rate is not consistent, with about 5% of screencaps taking longer than 80ms.) The output video file played back at 12.5 fps as expected, but only contained 371 frames. So at 12.5 fps, 371 frames play back in 29 seconds. That's still twice the expected speed, so matching frame rate to grab rate hasn't worked.

    After a bit of research, it seems you can pass two frame rates to FFmpeg. From the documentation (end of section 2):
    To force the frame rate of the input file (valid for raw formats only) to 1 fps and the frame rate of the output file to 24 fps:

    ffmpeg -r 1 -i input.m2v -r 24 output.avi
    Quite how that applies to streaming a bitmap, I don't know, but it does have an affect on the results.

    After a fair bit of trial and error and a lot of observation, I deduced the following points:
    If you don't specify a value for the input rate, it defaults to 25.
    If you don't specify a value for the output rate, it defaults to the input rate, or if no input rate has been specified, the input rate's default value.
    The actual number of frames present in the output video seems to be derived as:

    num frames in video = num screen caps * ( output rate / input rate )

    From that last point, it can be shown (I won't bore you with the maths) that the undesired speed factor is given by:

    speed factor = input rate / screen grab rate

    So in the above example, where I hadn't specified an input rate, it will have defaulted to 25fps, the screen grab rate was capped at 12.5 fps, which gives:

    speed factor = 25 / 12.5 = 2

    and indeed, the video payed twice as fast as I expected.


    Another example:

    Screen grab rate capped at 12.5fps (80ms timing loop)
    Grabbed 744 frames in 60 seconds
    Actual Screen Grab rate = 744 / 60 = 12.4fps

    Input rate set = 18fps
    Output rate set = 12.5fps

    and here come the calculations:

    Expected frames in video = num screen grabs * ( output rate / input rate )
    = 744 * ( 12.5 / 18 ) = 517

    Speed factor = input rate / screen grab rate = 18 / 12.4 = 1.4516
    which gives expected video run time of 60 / 1.4516 = 41.3337 seconds.

    And these values compare well to the actual values for the video produced:

    video contains 518 frames,
    playback rate = 12.5 fps,
    run time = 41.440 seconds.


    So my current thinking would be to cap the screen grab rate at a value that the PC hardware can comfortably cope with (12.5 to 15 fps for my PC @ 1920x1080 screen res.), ony pass the input rate as an argument to FFmpeg (which will then be used by default as the output rate), and as the input rate value, use the same value as the screen grab rate is capped to.
    Code:
    proc.StartInfo.Arguments = "-r 12.5 -f image2pipe -i pipe:.bmp -pix_fmt yuv420p -c:v libx264 -an -bufsize 60000k -b:v 1800k -y -threads 2 " & CaptureDir & "test.mp4"
    As long as the input rate always equals the screen grab rate, then the speed factor (input rate / screen grab rate ) will always be 1.


    I should add that I know nothing about FFmpeg, and there may well be a command line that does all this in a sensible manner. I should read the documentation for FFmpeg, but there's far too much of it for me to do that at the moment. Perhaps someone knows of a simpler method, and would be willing to share?
    Last edited by Inferrd; Jun 24th, 2014 at 04:21 PM.

  19. #19
    VB For Fun Edgemeal's Avatar
    Join Date
    Sep 2006
    Location
    WindowFromPoint
    Posts
    4,255

    Re: VB.NET - Screen Recorder with audio. Converts to MPEG-4 video now. Update 29 Dec

    Quote Originally Posted by Inferrd View Post
    @Edgemeal: Nice work on the screen grab code.
    Thanks for checking it out, I know I tried what you did and was just mad I couldn't get more FPS, I give up this for now.

    btw, I updated post #17 for anyone interested in the way I add the mouse pointer and red circle to the captures.

    UPDATE Did a couple quick timing test @ 1920x1080, my capture takes about 24ms, and the write to ffmpeg is another 24-30ms, and every so often there is a spike where it adds another 20~30ms to the total time. I just assumed writing to ffmpeg would be super fast.

    Also tried saving the bmp captures directly to files on the fly and it only takes about 5.5 ~ 5.7m to save them.
    Last edited by Edgemeal; Jun 24th, 2014 at 11:35 PM.

  20. #20

    Thread Starter
    Fanatic Member Peter Porter's Avatar
    Join Date
    Jul 2013
    Posts
    532

    Re: VB.NET - Screen Recorder with audio. Converts to MPEG-4 video now. Update 29 Dec

    Hi Edgemeal. I do have a fix that I created back in January. It's not perfect. Sometimes the video plays back too slow, or the frame rate fluctuates, so it's never in sync. Basically it merges the saved video with the saved audio, but maybe if I could merge both together while recording, it could improve the syncronization. I'm gonna play with it a bit now and upload this version, maybe tonight.
    Last edited by Peter Porter; Jun 25th, 2014 at 09:04 AM.

  21. #21

    Thread Starter
    Fanatic Member Peter Porter's Avatar
    Join Date
    Jul 2013
    Posts
    532

    Re: VB.NET - Screen Recorder with audio. Converts to MPEG-4 video now. Update 29 Dec

    Great screen recorder, Edgemeal!

    I posted an update, but I'm gonna rewrite it using both of our ideas. My project is still not perfect. It's records YouTube fullscreen videos almost in sync, but if you're not recording videos, then it's grossly out of sync. Gonna add options to where a user can set what kinda of capture is going to be performed so the program could adjust to a set frame rate.

    What I'm trying to workout now is to play the created video in a user's system's default Media Player. It's currently broke.

  22. #22
    VB For Fun Edgemeal's Avatar
    Join Date
    Sep 2006
    Location
    WindowFromPoint
    Posts
    4,255

    Re: VB.NET - Screen Recorder with audio. Converts to MPEG-4 video now. Update 29 Dec

    Was playing with your july 14 code, not much difference, playback is still too fast, On my pc calls to ffmpeg are taking about 30ms, and screenshot (@ 1920x1080) adds another 25ms+, so time to capture a frame might take 60ms which already limits me to 16.6FPS, so for quick test I changed both -r commands to -r 15 and playback speed was about perfect, but 15FPS is just too choppy for capturing video, So its really not your code, my PC just cant do a screenshot and also call ffmpeg fast enough to do decent FPS captures.

  23. #23
    New Member
    Join Date
    Oct 2014
    Posts
    5

    Cool Re: VB.NET - Screen Recorder with audio. Converts to MPEG-4 video now. Update 29 Dec

    Name:  Recorder.jpg
Views: 12518
Size:  35.9 KBCapture2Vid.zip

    I just tried editing Peter Porter's project a bit...

    With new skin and few extra functions..
    1. Recording Mouse pointer too.
    2. Displaying Left and Right mouse button clicks.

    And an embedded Windows Media Player.

    Note: I havent added the ffmpeg.exe in this pakage.also i have compressed it two times cos of size restrictions.

  24. #24

    Thread Starter
    Fanatic Member Peter Porter's Avatar
    Join Date
    Jul 2013
    Posts
    532

    Re: VB.NET - Screen Recorder with audio. Converts to MPEG-4 video now. Update 29 Dec

    Great job, JoeDeGeek!

    I'll have my latest version uploaded soon for you to tweak. Still looks the same, but with a few extras, a whole lot better than before.
    Last edited by Peter Porter; Nov 21st, 2014 at 09:34 PM.

  25. #25
    Hyperactive Member
    Join Date
    Dec 2009
    Posts
    340

    Question Re: VB.NET - Screen Recorder with audio. Converts to MPEG-4 video now. Update 29 Dec

    Quote Originally Posted by Edgemeal View Post
    First of all thanks for sharing!
    I would love to see a fix for the playback speed, I've tried all sorts of command line options for ffmpeg but the output file was always playing about 2x faster then the real capture time.
    Dear sir, greetings. hope you are fine

    sir, i have tried your sample/example:

    And this is my modified code:
    Code:
            Dim objBitmap As System.Drawing.Bitmap
            Dim objFProcess As System.Diagnostics.Process
            Dim objStream As System.IO.BinaryWriter
            Dim strFiles() As String
            Dim strEachFile As String
            Dim intFile As Integer
            Dim intFrame As Integer
            Dim intFLoop As Integer
            objFProcess = New System.Diagnostics.Process
            objFProcess.StartInfo.FileName = "c:\ffmpeg.exe"
            objFProcess.StartInfo.Arguments = "-r 1 -f image2pipe -i pipe:.bmp -pix_fmt yuv420p -crf 35.0 -vcodec libx264 -an -coder 1 -rc_lookahead 50 -threads 0 D:\test.mp4"
            objFProcess.StartInfo.UseShellExecute = False
            objFProcess.StartInfo.RedirectStandardInput = True
            objFProcess.StartInfo.RedirectStandardOutput = True
            objFProcess.StartInfo.RedirectStandardError = True
            'objFProcess.StartInfo.WindowStyle = ProcessWindowStyle.Hidden
            'objFProcess.StartInfo.CreateNoWindow = True
            objFProcess.Start()
            objStream = New System.IO.BinaryWriter(objFProcess.StandardInput.BaseStream)
            strFiles = My.Computer.Clipboard.GetText().Split({System.Environment.NewLine}, StringSplitOptions.None)
            intFrame = 0
            intFile = 0
            For Each strEachFile In strFiles
                'MessageBox.Show(strEachFile)
                intFile = intFile + 1
                objBitmap = New System.Drawing.Bitmap(strEachFile)
                For intFLoop = 0 To 24
                    intFrame = intFrame + 1
                    cmd1.Text = intFile.ToString & "-" & intFrame.ToString
                    My.Application.DoEvents()
                    objBitmap.Save(objStream.BaseStream, System.Drawing.Imaging.ImageFormat.Bmp) Rem this line give me below (attached) error :(
                Next
                objBitmap.Dispose()
            Next
            System.Threading.Thread.Sleep(3000)
            objStream.Close()
            MessageBox.Show("Done!")
            'objFProcess.Kill()
    And Here is the error:
    Attachment 123451

    FYI your sample also raise same error

    can you please help me out?

    thanks in advance....

    best regards

  26. #26

    Thread Starter
    Fanatic Member Peter Porter's Avatar
    Join Date
    Jul 2013
    Posts
    532

    Re: VB.NET - MPEG-4 Screen recorder. Update 14 Feb 2015

    I've attached the screen capture zipped project file in my first post above. Capture is now done with a background worker.

    Code:
    Option Strict On
    
    Imports System.IO
    Imports System.Net
    Imports System.Text
    Imports System.Threading
    Imports System.Drawing
    Imports System.Drawing.Image
    Imports System.Runtime.InteropServices
    
    Public Class Form1
    
        'dll import and initializing function needed for recording and saving audio
        <DllImport("winmm.dll")> _
        Private Shared Function mciSendString(ByVal command As String, ByVal buffer As String, ByVal bufferSize As Integer, ByVal hwndCallback As IntPtr) As Integer
        End Function
    
        'for dragging form
        Dim drag As Boolean
        Dim a As Integer
        Dim b As Integer
    
        'to get screen resolution
        Dim MW As Integer = Screen.PrimaryScreen.Bounds.Width
        Dim MH As Integer = Screen.PrimaryScreen.Bounds.Height
        Dim MH2 As Integer
        Public ScreenSize As Size = New Size(MW, MH)
        Dim bdr As Integer = 152
        Dim bdr2 As Integer
    
        'get mouse position, and set it's bitmap
        Dim mousex As Integer
        Dim mousey As Integer
        Dim mousecursor As Bitmap
    
        'for the ffmpeg processes, started in Record button sub
        Dim proc As New Process
        Dim proc2 As New Process
    
        'for the ffmpeg merge process, located in BW2 (background worker)
        Dim proc3 As New Process
    
        'for the play process
        Dim proc4 As New Process
    
        'Used within the video recording Backgroundworker sub, renamed BW1
        Dim audiostr As String = "Stereo Mix (Realtek High Defini"
        Dim istr As FileStream
        Dim stopwatch1 As New Stopwatch
        Dim stopwatch2 As New Stopwatch
        Dim fcounter As Integer = 1
        Dim Frames As String
    
        'for date and time in final video's filename
        Dim strDate As String
    
        'timer for 2nd Backgroundworker, BW2
        Dim stopwatch3 As New Stopwatch
    
        'directory path to system's video folder where Captured folder will be created
        Dim dir As String = Environment.GetFolderPath(Environment.SpecialFolder.MyVideos)
    
    
        Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
            'creates required folder for captured video and audio if it doesn't already exist
            If My.Computer.FileSystem.DirectoryExists(dir) = False Then
                Throw New Exception("The specified Directory doesn't exist. Please check it's spelling.")
            ElseIf My.Computer.FileSystem.DirectoryExists(dir & "\" & "\Captured") Then
            Else
                My.Computer.FileSystem.CreateDirectory(dir & "\" & "\Captured")
            End If
    
            MH2 = MH
            'set crop of capture if the primary screen height is 1024
            If MW = 1280 And MH = 1024 Then
                MH2 = 720
            Else
            End If
    
        End Sub
    
        'next 3 subs is for dragging the application
        Private Sub Form1_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseDown
            drag = True
            a = Windows.Forms.Cursor.Position.X - Me.Left
            b = Windows.Forms.Cursor.Position.Y - Me.Top
        End Sub
    
    
        Private Sub Form1_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseMove
            If drag Then
                Me.Top = Windows.Forms.Cursor.Position.Y - b
                Me.Left = Windows.Forms.Cursor.Position.X - a
            End If
        End Sub
    
    
        Private Sub Form1_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseUp
            drag = False
        End Sub
    
    
        Private Sub Record_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Record.Click
            CloseButton.Enabled = False
            StopRec.Enabled = True
            Play.Enabled = False
            bdr = 152
            stopwatch2.Reset()
    
            'starts ffmpeg process for mp3 capture
            proc.StartInfo.FileName = Application.StartupPath + "\ffmpeg.exe"
            proc.StartInfo.Arguments = String.Format("-f dshow -i audio=""" + audiostr + """ -acodec libmp3lame -b:a 128k -y " + dir + "\Captured\CapturedAudio.mp3")
            proc.StartInfo.UseShellExecute = False
            proc.StartInfo.WindowStyle = ProcessWindowStyle.Hidden
            proc.StartInfo.RedirectStandardInput = True
            proc.StartInfo.RedirectStandardOutput = True
            proc.StartInfo.CreateNoWindow = True
            proc.Start()
    
            'starts ffmpeg process for captured frames
            proc2.StartInfo.FileName = Application.StartupPath + "\ffmpeg.exe"
            proc2.StartInfo.Arguments = String.Format("-f image2pipe -r 30 -i pipe:.bmp -pix_fmt yuv420p -c:v libx264 -crf 18 -g 1 -y -r 30 " + dir + "\Captured\Temp.mp4")
            proc2.StartInfo.UseShellExecute = False
            proc2.StartInfo.WindowStyle = ProcessWindowStyle.Hidden
            proc2.StartInfo.RedirectStandardInput = True
            proc2.StartInfo.RedirectStandardOutput = True
            proc2.StartInfo.CreateNoWindow = True
            proc2.Start()
    
            Label4.Text = "Recording"
    
            BW1.RunWorkerAsync()
    
            Record.Enabled = False
        End Sub
    
    
        Private Sub StopRec_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles StopRec.Click
            strDate = DateTime.Now.ToString("ddMMMyyyy_hhmmss")
            CloseButton.Enabled = True
            Label4.Text = "Saving..."
            MediaMerger.Enabled = True
            Play.Enabled = True
            Record.Enabled = True
        End Sub
    
    
        Private Sub Play_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Play.Click
            proc4.StartInfo.FileName = dir + "\Captured\Movie.mp4"
            proc4.Start()
        End Sub
    
    
        Private Sub MinimizeButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MinimizeButton.Click
            Me.WindowState = FormWindowState.Minimized
        End Sub
    
    
        Private Sub CloseButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles CloseButton.Click
            Me.Close()
        End Sub
    
    
        'delegate & sub used by BW2 (backgroundworker)
        Delegate Sub SetLabelTextInvoker(ByVal label As Label, ByVal Text As String)
    
        Sub SetLabelText(ByVal Label As Label, ByVal Text As String)
            If Label4.InvokeRequired = True Then
                Label4.Invoke(New SetLabelTextInvoker(AddressOf SetLabelText), Label, Text)
            Else
                Label4.Text = Text
            End If
        End Sub
    
    
        'delegate & sub used by BW1 (backgroundworker)
        Delegate Sub SetLabelTextInvoker2(ByVal label As Label, ByVal Text As String)
    
        Sub SetLabelText2(ByVal Label As Label, ByVal Text As String)
            If Label6.InvokeRequired = True Then
                Label6.Invoke(New SetLabelTextInvoker2(AddressOf SetLabelText2), Label, Text)
            Else
                Label6.Text = Text
            End If
        End Sub
    
    
        'backgroundworker for capturing images and relaying them to ffmpeg for video creation
        Private Sub BW1_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles BW1.DoWork
            On Error GoTo error_handler2
    
            
    
            Dim writer As New BinaryWriter(proc2.StandardInput.BaseStream)
    
            For i As Integer = 0 To 1000000
    
                stopwatch1.Start()
                stopwatch2.Start()
                Frames = Format(fcounter, "000000")
    
                Dim BMP As New System.Drawing.Bitmap(MW, MH2, System.Drawing.Imaging.PixelFormat.Format32bppArgb)
                Dim Cap As System.Drawing.Graphics = System.Drawing.Graphics.FromImage(BMP)
                Cap.CopyFromScreen(New Point(0, bdr), New Point(0, 0), ScreenSize, System.Drawing.CopyPixelOperation.SourceCopy)
    
    
    
    
                'if checkbox is checked, then the mouse will be recorded
                If CheckBox1.Checked = True Then
                    mousex = Cursor.Position.X
                    mousey = Cursor.Position.Y - bdr
                    mousecursor = New Bitmap(My.Resources.mouse)
                    Dim g As Graphics = Graphics.FromImage(BMP)
                    g.DrawImage(mousecursor, mousex, mousey)
    
                    If MW = 1280 And MH = 1024 Then
                        'capture region follows the mouse
                        If mousey <= bdr + 30 Then
                            bdr = CInt(mousey - 30)
                            If bdr < 0 Then
                                bdr = 0
                            Else
                            End If
                        Else
                            If mousey >= 690 Then
                                bdr2 = mousey + bdr
                                bdr = bdr2 - mousey
                                bdr = bdr + 30
                                If bdr >= 304 Then
                                    bdr = 304
                                Else
                                End If
                            Else
                            End If
                        End If
    
                    Else
                    End If
                Else
                End If
    
    
                BMP.Save(writer.BaseStream, System.Drawing.Imaging.ImageFormat.Bmp)
    
                If Label4.Text = "Saving..." Then
                    BMP.Dispose()
                    Cap.Dispose()
                    GC.Collect()
                    writer.Close()
                    stopwatch1.Stop()
                    stopwatch2.Stop()
                    proc.StandardInput.WriteLine("q")
                    BW1.CancelAsync()
                Else
                    BW1.ReportProgress(i)
                End If
    
                fcounter = fcounter + 1
                i = i + 1
    
                BMP.Dispose()
                Cap.Dispose()
                GC.Collect()
    
                'below code displays time during capture
                'uses SetLabelTextInvoker2 delegate, SetLabelText2 sub, label6 & custom stopwatch (timer2)
                SetLabelText2(Label6, CStr(stopwatch2.Elapsed.ToString("hh\:mm\:ss\.fff")))
    
                'Do Until Loop for ensuring capture interval, which is purposely not set to-
                '400000 (actual interval for 25fps), because the For Next loop wastes time during loop
                Do
                Loop Until stopwatch1.Elapsed.Ticks >= 333040
                stopwatch1.Reset()
    
            Next
    error_handler2:
        End Sub
    
    
        Private Sub BW1_ProgressChanged(ByVal sender As Object, ByVal e As System.ComponentModel.ProgressChangedEventArgs) Handles BW1.ProgressChanged
            'for Captured Frames counter
            Label2.Text = Convert.ToString(Frames)
        End Sub
    
    
        'started by the MediaMerger timer, this backgroundworker detects if ffmpeg is done merging audio with video
        Private Sub BW2_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles BW2.DoWork
            For i As Integer = 0 To 1000000
                stopwatch3.Start()
                BW2.ReportProgress(i)
                If Process.GetProcessesByName("ffmpeg").Length > 0 Then
                Else
                    stopwatch3.Stop()
                    SetLabelText(Label4, "Done")
                    BW2.CancelAsync()
                    Exit Sub
                End If
            Next
        End Sub
    
        Private Sub BW2_ProgressChanged(ByVal sender As Object, ByVal e As System.ComponentModel.ProgressChangedEventArgs) Handles BW2.ProgressChanged
        End Sub
    
    
        Private Sub MediaMerger_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MediaMerger.Tick
            'starts ffmpeg detector to detect if it's still running
            BW2.RunWorkerAsync()
    
            'stopwatch delayer to give enough time for captured audio and video to save before merge
            stopwatch1.Start()
            Do
            Loop Until stopwatch1.Elapsed.Ticks >= 999999
            stopwatch1.Stop()
    
            'merges the audio with the video, with a final date & Time filename, ex. 15Feb2015_124202.mp4
            proc3.StartInfo.FileName = Application.StartupPath + "\ffmpeg.exe"
            proc3.StartInfo.Arguments = String.Format("-r 30 -i " + dir + "\Captured\Temp.mp4 -i " + dir + "\Captured\CapturedAudio.mp3 -r 30 -c:v copy -c:a aac -async 30 -strict experimental -map 0 -map 1 -y " + dir + "\Captured\" + strDate + ".mp4")
            proc3.StartInfo.UseShellExecute = False
            proc3.StartInfo.WindowStyle = ProcessWindowStyle.Hidden
            proc3.StartInfo.RedirectStandardInput = True
            proc3.StartInfo.RedirectStandardOutput = True
            proc3.StartInfo.CreateNoWindow = True
            proc3.Start()
    
            StopRec.Enabled = False
    
            'resets Frames' counter
            fcounter = 1
    
            MediaMerger.Enabled = False
        End Sub
    End Class
    Last edited by Peter Porter; Feb 22nd, 2015 at 10:24 AM.

  27. #27

    Thread Starter
    Fanatic Member Peter Porter's Avatar
    Join Date
    Jul 2013
    Posts
    532

    Re: VB.NET - MPEG-4 Screen recorder. Update 14 Feb 2015

    The screen capture video recorder has been updated.

    * It now has the option to record the mouse smoothly, which can also be selected or deselected during the capture.

    * After capture, the final merged video has a unique Date & Time filename.

    * Audio is captured to mp3, which is merged with the captured video automatically.

    Hope you find this project useful!
    Last edited by Peter Porter; Feb 15th, 2015 at 08:14 AM.

  28. #28

    Thread Starter
    Fanatic Member Peter Porter's Avatar
    Join Date
    Jul 2013
    Posts
    532

    Re: VB.NET - MPEG-4 Screen recorder. 22 Feb 2015 update

    Updated the screen recorder.

    * Mouse capture and display is now accurate.

    * Captured region follows the mouse automatically, but only if the screen resolution is 1280x1024, which is cropped to 1280x720.

    * Other tweaks.

  29. #29
    Bad man! ident's Avatar
    Join Date
    Mar 2009
    Location
    Cambridge
    Posts
    5,398

    Re: VB.NET - MPEG-4 Screen recorder. 22 Feb 2015 update

    Some strange things going on with that example. Like for example you use an environment variable thats created by the system yet if it does not exist ask the user to check the spelling. How do they have any control over it?

  30. #30

    Thread Starter
    Fanatic Member Peter Porter's Avatar
    Join Date
    Jul 2013
    Posts
    532

    Re: VB.NET - MPEG-4 Screen recorder. 22 Feb 2015 update

    ident, I removed that check for that environment variable. It only checks for the Captured folder now.

    I've made some other changes and fixes, but I'm gonna rebuild this whole project from scratch to see if that fixes one major issue. I can't publish a working installation executable. But the weird thing, from my updated app that I haven't posted to replace the above zip, if I copy the executable from the bin Debug folder to another folder outside the project and run it, my app works fine.
    Last edited by Peter Porter; Mar 23rd, 2015 at 06:06 AM.

  31. #31

    Thread Starter
    Fanatic Member Peter Porter's Avatar
    Join Date
    Jul 2013
    Posts
    532

    Post MPEG-4 Screen recorder. May 23rd, 2015 code, pt1

    Code for April 10th, 2015 update

    Since it's too long to add to the top post, I have to split it between 4 posts:

    From the Properties sidepanel:
    * Set FormBorderStyle to None
    * DoubleBuffered to True
    * Size 645x72

    Controls:
    * 2 backgroundworkers named BW1 and BW2
    * Timer named MediaMerger
    * 5 Buttons named Record, StopRec, Play, MinimizeButton, CloseButton
    * CheckBox: From it's properties, enter "Record Mouse" for Text
    * 7 labels
    Label 1's Text is "Captured Frames:"
    Label 2's Text is "000000"
    Label 3's Text is "Status:
    Label 4's Text is "--------------"
    Label 5's Text is "Time:"
    Label 6's Text is "00:00:00.000"
    Label 7's Text is "hr min sec msec"

    Extra forms used as regionbars:
    * 2 forms named TopBar and BottomBar

    Project's Resources:
    * Mouse image, png or jpeg
    * FFmpeg.exe - download either the 32bit or 64bit static builds and add ffmpeg.exe to resources.
    * BackgroundImage for Topbar and Bottombar forms. (No image? Set their BackColor's to DarkSeaGreen)

    Form1's code:
    Code:
    Option Strict On
    
    Imports System.IO
    Imports System.Net
    Imports System.Text
    Imports System.Threading
    Imports System.Drawing
    Imports System.Drawing.Image
    Imports System.Runtime.InteropServices
    
    Public Class Form1
    
        ' P/Invoke declarations
        <DllImport("gdi32.dll")> _
        Private Shared Function BitBlt(ByVal hdcDest As IntPtr, ByVal xDest As Integer, ByVal yDest As Integer, ByVal wDest As Integer, ByVal hDest As Integer, ByVal hdcSource As IntPtr, _
       ByVal xSrc As Integer, ByVal ySrc As Integer, ByVal rop As CopyPixelOperation) As Boolean
        End Function
        <DllImport("user32.dll")> _
        Private Shared Function ReleaseDC(ByVal hWnd As IntPtr, ByVal hDc As IntPtr) As Boolean
        End Function
        <DllImport("gdi32.dll")> _
        Private Shared Function DeleteDC(ByVal hDc As IntPtr) As IntPtr
        End Function
        <DllImport("gdi32.dll")> _
        Private Shared Function DeleteObject(ByVal hDc As IntPtr) As IntPtr
        End Function
        <DllImport("gdi32.dll")> _
        Private Shared Function CreateCompatibleBitmap(ByVal hdc As IntPtr, ByVal nWidth As Integer, ByVal nHeight As Integer) As IntPtr
        End Function
        <DllImport("gdi32.dll")> _
        Private Shared Function CreateCompatibleDC(ByVal hdc As IntPtr) As IntPtr
        End Function
        <DllImport("gdi32.dll")> _
        Private Shared Function SelectObject(ByVal hdc As IntPtr, ByVal bmp As IntPtr) As IntPtr
        End Function
        <DllImport("user32.dll")> _
        Public Shared Function GetDesktopWindow() As IntPtr
        End Function
        <DllImport("user32.dll")> _
        Public Shared Function GetWindowDC(ByVal ptr As IntPtr) As IntPtr
        End Function
    
        'for dragging form
        Dim drag As Boolean
        Dim a As Integer
        Dim b As Integer
    
        'to get screen resolution
        Dim MW As Integer = Screen.PrimaryScreen.Bounds.Width
        Dim MH As Integer = Screen.PrimaryScreen.Bounds.Height
        Dim AspectH As Integer = CInt(Screen.PrimaryScreen.Bounds.Width / 1920 * 1080)
        Dim totalp As Integer
        Public ScreenSize As Size = New Size(MW, MH)
        Dim bdr As Integer = 0
        Dim bdr2 As Integer
    
        'get mouse position, and set it's bitmap
        Dim mousex As Integer
        Dim mousey As Integer
        Dim mousecursor As Bitmap
    
        'for the ffmpeg processes, started in Record button sub
        Dim proc As New Process
        Dim proc2 As New Process
    
        'for the ffmpeg merge process, located in BW2 (background worker)
        Dim proc3 As New Process
    
        'for the play process
        Dim proc4 As New Process
    
        'for overwritting temp file before deletion
        Dim BMP3 As New Bitmap(1, 1)
    
        'Used within the video recording Backgroundworker sub (BW1)
        Dim audiostr As String = "Stereo Mix (Realtek High Defini"
        Dim istr As FileStream
        Dim stopwatch1 As New Stopwatch
        Dim stopwatch2 As New Stopwatch
        Dim fcounter As Integer = 1
        Dim Frames As String
        Dim rr As Integer
        Dim fps As Integer
        Dim CLoop As Integer
    
        'for date and time in final video's filename
        Dim strDate As String
    
        'timer for 2nd Backgroundworker, BW2
        Dim stopwatch3 As New Stopwatch
    
        'directory path to system's video folder where Captured folder will be created
        Dim dir As String = Environment.GetFolderPath(Environment.SpecialFolder.MyVideos)
    
    
        Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
            Dim pProcess() As Process = System.Diagnostics.Process.GetProcessesByName("ffmpeg")
    
            For Each p As Process In pProcess
                p.Kill()
            Next
    
    
            'creates required folder for captured video and audio if it doesn't already exist
            If My.Computer.FileSystem.DirectoryExists(dir & "\" & "\Captured") = False Then
                My.Computer.FileSystem.CreateDirectory(dir & "\" & "\Captured")
            Else
            End If
    
            'delayer, to give enough time for the captured folder to be created
            stopwatch1.Start()
            Do
            Loop Until stopwatch1.Elapsed.Ticks >= 333040
            stopwatch1.Reset()
            stopwatch1.Stop()
    
            'extracts ffmpeg from resources to the captured folder
            If My.Computer.FileSystem.FileExists("C:\Users\Web\Videos\Captured\ffmpeg.exe") = False Then
                savefromresources("C:\Users\Web\Videos\Captured\ffmpeg.exe", My.Resources.ffmpeg)
            Else
            End If
    
            'application location at runtime
            Dim appx As Integer = MW
            Dim appy As Integer = MH
            appx = CInt((appx - 645) / 2)
            appy = CInt((appy - 72) / 2)
            Me.Location = New Point(appx, appy)
    
            'sets fps for ffmpeg, and BW1's (backgroundworker) capture interval loop
            totalp = MW * MH
            If totalp <= 921600 Then
                fps = 30
                CLoop = 333333
            Else
                fps = 25
                CLoop = 400000
            End If
    
            'if AspectH (primary screen's width / 1920 * 1080) is less than the
            'primary screen's height, the "Crop to 16.9" checkbox is set to visible
            If AspectH < Screen.PrimaryScreen.Bounds.Height Then
                CheckBox2.Visible = True
            Else
            End If
    
        End Sub
    
    
        Public Sub savefromresources(ByVal filepath As String, ByVal file As Object)
            Dim fbyte() As Byte = CType(file, Byte())
            My.Computer.FileSystem.WriteAllBytes(filepath, fbyte, True)
        End Sub
    
    
        'next 3 subs is for dragging the application
        Private Sub Form1_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseDown
            drag = True
            a = Windows.Forms.Cursor.Position.X - Me.Left
            b = Windows.Forms.Cursor.Position.Y - Me.Top
        End Sub
    
    
        Private Sub Form1_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseMove
            If drag Then
                Me.Top = Windows.Forms.Cursor.Position.Y - b
                Me.Left = Windows.Forms.Cursor.Position.X - a
            End If
        End Sub
    
    
        Private Sub Form1_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseUp
            drag = False
        End Sub
    
    
        Private Sub Record_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Record.Click
            CheckBox2.Enabled = False
    
            If CheckBox2.Checked = False And totalp > 921600 Then
                fps = 25
                CLoop = 400000
                MW = Screen.PrimaryScreen.Bounds.Width
                MH = Screen.PrimaryScreen.Bounds.Height
                bdr = 0
            Else
                fps = 30
                CLoop = 333040
                bdr = CInt((Screen.PrimaryScreen.Bounds.Height - AspectH) / 2)
            End If
    
            Me.WindowState = FormWindowState.Minimized
    
            'set crop of capture if the primary screen height is 1024
            If CheckBox2.Checked = True Then
                TopBar.Top = -152
                BottomBar.Top = Screen.PrimaryScreen.Bounds.Height - 152
                TopBar.Show()
                BottomBar.Show()
                TopBar.TopMost = True
                BottomBar.Size = New System.Drawing.Size(1280, 111)
                bdr = CInt((Screen.PrimaryScreen.Bounds.Height - AspectH) / 2)
                MH = AspectH
                If CheckBox1.Checked = True Then
                    BottomBar.Size = New System.Drawing.Size(1280, 304)
                    BottomBar.TopMost = True
                Else
                End If
            Else
            End If
    
            'overwritting/deleting temp mp4. Reason for this, sometimes capturing wont overwrite the temp mp4.
            Try
                BMP3.Save("C:\Users\Web\Videos\Captured\Temp.mp4")
            Catch ex As Exception
    
                BottomBar.Size = New System.Drawing.Size(1280, BottomBar.Height - 30)
                MsgBox("Temp.mp4 is in use. It must be free in order to capture.")
                Exit Sub
            End Try
    
            stopwatch1.Start()
            Do
            Loop Until stopwatch1.Elapsed.Ticks >= 333040
            stopwatch1.Reset()
            stopwatch1.Stop()
            System.IO.File.Delete("C:\Users\Web\Videos\Captured\Temp.mp4")
    
            CloseButton.Enabled = False
            StopRec.Enabled = True
            Play.Enabled = False
            stopwatch2.Reset()
    
            'starts ffmpeg process for mp3 capture
            proc.StartInfo.FileName = "C:\Users\Web\Videos\Captured\ffmpeg.exe"
            proc.StartInfo.Arguments = String.Format("-f dshow -i audio=""" + audiostr + """ -acodec libmp3lame -b:a 128k -y " + dir + "\Captured\CapturedAudio.mp3")
            proc.StartInfo.UseShellExecute = False
            proc.StartInfo.WindowStyle = ProcessWindowStyle.Hidden
            proc.StartInfo.RedirectStandardInput = True
            proc.StartInfo.RedirectStandardOutput = True
            proc.StartInfo.CreateNoWindow = True
            proc.Start()
    
            'starts ffmpeg process for captured frames
            proc2.StartInfo.FileName = "C:\Users\Web\Videos\Captured\ffmpeg.exe"
            proc2.StartInfo.Arguments = String.Format("-f image2pipe -r " & fps & " -i pipe:.bmp -pix_fmt yuv420p -c:v libx264 -crf 18 -g 1 -y -r " & fps & " " & dir & "\Captured\Temp.mp4")
            proc2.StartInfo.UseShellExecute = False
            proc2.StartInfo.WindowStyle = ProcessWindowStyle.Hidden
            proc2.StartInfo.RedirectStandardInput = True
            proc2.StartInfo.RedirectStandardOutput = True
            proc2.StartInfo.CreateNoWindow = True
            proc2.Start()
    
    
           
            Label4.Text = "Recording"
    
            BW1.RunWorkerAsync()
    
            Record.Enabled = False
        End Sub
    
    
        Private Sub StopRec_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles StopRec.Click
            CheckBox2.Enabled = True
            strDate = DateTime.Now.ToString("ddMMMyyyy_hhmmss")
            Label4.Text = "Saving..."
                TopBar.Hide()
                BottomBar.Hide()
                MediaMerger.Enabled = True
                'starts background worker to detect if the ffmpeg audio save process is still running
                BW2.RunWorkerAsync()
        End Sub
    
    
        Private Sub Play_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Play.Click
            proc4.StartInfo.FileName = dir + "\Captured\" & strDate & ".mp4"
            proc4.Start()
        End Sub
    
    
        Private Sub MinimizeButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MinimizeButton.Click
            Me.WindowState = FormWindowState.Minimized
        End Sub
    
    
        Private Sub CloseButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles CloseButton.Click
            Me.Close()
        End Sub
    Continued in next post...
    Last edited by Peter Porter; Jul 20th, 2015 at 09:39 AM.

  32. #32

    Thread Starter
    Fanatic Member Peter Porter's Avatar
    Join Date
    Jul 2013
    Posts
    532

    Post MPEG-4 Screen recorder. May 23rd, 2015 code, pt2

    ...continued. Form1's code:
    Code:
    'delegate & sub used by BW2 (backgroundworker)
        Delegate Sub SetLabelTextInvoker(ByVal label As Label, ByVal Text As String)
    
        Sub SetLabelText(ByVal Label As Label, ByVal Text As String)
            If Label4.InvokeRequired = True Then
                Label4.Invoke(New SetLabelTextInvoker(AddressOf SetLabelText), Label, Text)
            Else
                Label4.Text = Text
            End If
        End Sub
    
    
        'delegate & sub used by BW1 (backgroundworker)
        Delegate Sub SetLabelTextInvoker2(ByVal label As Label, ByVal Text As String)
    
        Sub SetLabelText2(ByVal Label As Label, ByVal Text As String)
            If Label6.InvokeRequired = True Then
                Label6.Invoke(New SetLabelTextInvoker2(AddressOf SetLabelText2), Label, Text)
            Else
                Label6.Text = Text
            End If
        End Sub
    
    
        'backgroundworker for capturing images and relaying them to ffmpeg for video creation
        Private Sub BW1_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles BW1.DoWork
    
            Try
    
                Dim writer As New BinaryWriter(proc2.StandardInput.BaseStream)
    
                For i As Integer = 0 To 1000000
    
                    stopwatch1.Start()
                    stopwatch2.Start()
                    Frames = Format(fcounter, "000000")
    
                  
                    Dim hDesk As IntPtr = GetDesktopWindow()
                    Dim hSrce As IntPtr = GetWindowDC(hDesk)
                    Dim hDest As IntPtr = CreateCompatibleDC(hSrce)
                    Dim hBmp As IntPtr = CreateCompatibleBitmap(hSrce, MW, MH)
                    Dim hOldBmp As IntPtr = SelectObject(hDest, hBmp)
                    Dim b As Boolean = BitBlt(hDest, 0, 0, MW, MH, hSrce, 0, bdr, CopyPixelOperation.SourceCopy Or CopyPixelOperation.CaptureBlt)
                    Dim bmp As Bitmap = Bitmap.FromHbitmap(hBmp)
                    SelectObject(hDest, hOldBmp)
                    DeleteObject(hBmp)
                    DeleteDC(hDest)
                    ReleaseDC(hDesk, hSrce)
    
    
                    'if checkbox is checked, then the mouse will be recorded
                    If CheckBox1.Checked = True Then
                        mousex = Cursor.Position.X
                        mousey = Cursor.Position.Y - bdr
                        mousecursor = New Bitmap(My.Resources.mouse)
                        Dim g As Graphics = Graphics.FromImage(BMP)
                        g.DrawImage(mousecursor, mousex, mousey)
    
                        If AspectH < Screen.PrimaryScreen.Bounds.Height And CheckBox2.Checked = True Then
                            'capture region follows the mouse
                            If mousey <= bdr + 30 Then
                                bdr = CInt(mousey - 30)
                                If bdr < 0 Then
                                    bdr = 0
                                Else
                                End If
                            Else
                                If mousey >= 690 Then
    
                                    bdr = bdr + 30
                                    If bdr >= 304 Then
                                        bdr = 304
                                    Else
                                    End If
                                Else
                                End If
                            End If
    
                        Else
                        End If
                    Else
                    End If
    
    
                    BMP.Save(writer.BaseStream, System.Drawing.Imaging.ImageFormat.Bmp)
    
                    If Label4.Text = "Saving..." Then
                        BMP.Dispose()
                        'Cap.Dispose()
                        GC.Collect()
                        writer.Close()
                        stopwatch1.Stop()
                        stopwatch2.Stop()
                        proc.StandardInput.WriteLine("q")
                        BW1.CancelAsync()
                    Else
                        BW1.ReportProgress(i)
                    End If
    
                    fcounter = fcounter + 1
                    i = i + 1
    
                    BMP.Dispose()
                    'Cap.Dispose()
                    GC.Collect()
    
                    'below code displays time during capture
                    'uses SetLabelTextInvoker2 delegate, SetLabelText2 sub, label6 & custom stopwatch (timer2)
                    SetLabelText2(Label6, CStr(stopwatch2.Elapsed.ToString("hh\:mm\:ss\.fff")))
    
                    'Do Until Loop for ensuring capture interval, which is purposely not set to-
                    '400000 (actual interval for 25fps), because the For Next loop wastes time during loop
                    Do
                    Loop Until stopwatch1.Elapsed.Ticks >= CLoop
                    stopwatch1.Reset()
    
                Next
            Catch ex As Exception
            End Try
    
        End Sub
    
    
        Private Sub BW1_ProgressChanged(ByVal sender As Object, ByVal e As System.ComponentModel.ProgressChangedEventArgs) Handles BW1.ProgressChanged
            'for Captured Frames counter
            Label2.Text = Convert.ToString(Frames)
    
            If CheckBox1.Checked = True Then
                BottomBar.Size = New System.Drawing.Size(1280, 304)
                If mousey <= bdr + 30 Then
                    If bdr <= 0 Then
                        TopBar.Top = bdr - 304
                    Else
                        TopBar.Top = bdr - 304
                        BottomBar.Top = bdr + 720
                    End If
                Else
                    If mousey >= 512 Then
                        If bdr >= 304 Then
                            BottomBar.Top = 1025
                        Else
                            TopBar.Top = bdr - 304
                            BottomBar.Top = bdr + 720
                        End If
                    End If
                End If
            Else
    
            End If
    
            
    
        End Sub
    
    
        'started by the Stop button & MediaMerger timer, this backgroundworker detects if ffmpeg process is still running
        Private Sub BW2_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles BW2.DoWork
            For i As Integer = 0 To 1000000
    
                BW2.ReportProgress(i)
                If Process.GetProcessesByName("ffmpeg").Length > 0 Then
                Else
    
                    SetLabelText(Label4, "Done")
                    BW2.ReportProgress(i)
                    BW2.CancelAsync()
                    Exit Sub
                End If
            Next
        End Sub
    
        Private Sub BW2_ProgressChanged(ByVal sender As Object, ByVal e As System.ComponentModel.ProgressChangedEventArgs) Handles BW2.ProgressChanged
    
            If Label4.Text = "Done" Then
                CloseButton.Enabled = True
                Play.Enabled = True
                Record.Enabled = True
            End If
    
        End Sub
    
    
        Private Sub MediaMerger_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MediaMerger.Tick
    
            If Label4.Text = "Done" Then
                Label4.Text = " Merging Media"
    
                stopwatch1.Start()
                Do
                Loop Until stopwatch1.Elapsed.Ticks >= 999999
                stopwatch1.Reset()
    
                'starts background worker again to detect if the ffmpeg merge process is still running
                BW2.RunWorkerAsync()
    
                'merges the audio with the video, with a final date & Time filename, ex. 15Feb2015_124202.mp4
                proc3.StartInfo.FileName = "C:\Users\Web\Videos\Captured\ffmpeg.exe"
                proc3.StartInfo.Arguments = String.Format("-r " & fps & " -i " & dir & "\Captured\Temp.mp4 -i " & dir & "\Captured\CapturedAudio.mp3 -r " & fps & " -c:v copy -c:a aac -async " & fps & " -strict experimental -map 0 -map 1 -y " & dir & "\Captured\" & strDate & ".mp4")
                proc3.StartInfo.UseShellExecute = False
                proc3.StartInfo.WindowStyle = ProcessWindowStyle.Hidden
                proc3.StartInfo.RedirectStandardInput = True
                proc3.StartInfo.RedirectStandardOutput = True
                proc3.StartInfo.CreateNoWindow = True
                proc3.Start()
    
                StopRec.Enabled = False
    
                'resets Frames' counter
                fcounter = 1
    
                MediaMerger.Enabled = False
                
            Else
            End If
    
        End Sub
    
        Private Sub CheckBox2_CheckedChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles CheckBox2.CheckedChanged
            fps = 30
            CLoop = 333040
        End Sub
    End Class
    Next to posts contain code and information for the regionbar forms (TopBar, BottomBar).
    Last edited by Peter Porter; May 23rd, 2015 at 10:53 AM.

  33. #33

    Thread Starter
    Fanatic Member Peter Porter's Avatar
    Join Date
    Jul 2013
    Posts
    532

    Post MPEG-4 Screen recorder. May 23rd, 2015 code, pt3

    Code for TopBar form

    From the Properties sidepanel:
    * Set FormBorderStyle to None
    * DoubleBuffered to True
    * BackColor to DarkSeaGreen
    * Size 1280x304
    * Opacity to 75%

    Code:
    Public Class TopBar
    
        Private Sub TopBar_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
            Me.Location = New Point(0, -152)
            Me.TopMost = True
        End Sub
    End Class
    Last edited by Peter Porter; May 23rd, 2015 at 10:53 AM.

  34. #34

    Thread Starter
    Fanatic Member Peter Porter's Avatar
    Join Date
    Jul 2013
    Posts
    532

    Post MPEG-4 Screen recorder. May 23rd, 2015 code, pt4

    Code for BottomBar form

    From the Properties sidepanel:
    * Set FormBorderStyle to None
    * DoubleBuffered to True
    * BackColor to DarkSeaGreen
    * Size 1280x304
    * Opacity to 75%

    Code:
    Public Class BottomBar
    
        Private Sub BottomBar_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
            Me.Location = New Point(0, 874)
            Me.TopMost = True
        End Sub
    
    End Class
    Last edited by Peter Porter; May 23rd, 2015 at 10:54 AM.

  35. #35

    Thread Starter
    Fanatic Member Peter Porter's Avatar
    Join Date
    Jul 2013
    Posts
    532

    Re: MPEG-4 Screen recorder. April 8th, 2015 update

    Latest version adjusts frames per second (fps) and capture interval according to screen resolution's total pixels. Screen resolutions with a pixel total equal to or less than 921600 pixels (1280x720) are captured at 30fps. Larger pixel totals (1280x1024, 1920x1080, etc...) are captured at 25fps.

    It no longer automatically crops. You must check "Crop to 16.9". If "Record mouse" is checked, along with "Crop to 16.9", the capture region follows the mouse according to actual screen bounds height.
    Last edited by Peter Porter; Apr 9th, 2015 at 05:59 PM.

  36. #36

    Thread Starter
    Fanatic Member Peter Porter's Avatar
    Join Date
    Jul 2013
    Posts
    532

    Re: VB.NET - MPEG-4 Screen recorder. April 10th, 2015 update

    Just made a minor change.

    The "Crop to 16.9" checkbox is only visible if your monitor does not have an asect ratio of 16.9.

  37. #37

    Thread Starter
    Fanatic Member Peter Porter's Avatar
    Join Date
    Jul 2013
    Posts
    532

    Re: VB.NET - MPEG-4 Screen recorder. April 30th, 2015 update

    Fixed some issues, and cleaned up the code.

    Here's a preview of what I have in the works, using the same capture code above.

    Name:  Preview.png
Views: 9618
Size:  83.0 KB
    Last edited by Peter Porter; May 11th, 2015 at 03:43 PM.

  38. #38

    Thread Starter
    Fanatic Member Peter Porter's Avatar
    Join Date
    Jul 2013
    Posts
    532

    Re: VB.NET - MPEG-4 Screen recorder. May 23rd, 2015 update

    I fixed a few bugs.

    No more endless saves, or crashes during a restart of the screen recorder. This was caused by stopping the app from the VB dashboard during a recording, which left an FFmpeg process running. Now a check is done for any FFmpeg processes at initial runtime, which is then stopped before any recording is made.

    Regionbars issues have been solved. They are realigned, resized, and displayed for every recording.

  39. #39
    Registered User
    Join Date
    Jul 2015
    Posts
    1

    Re: VB.NET - MPEG-4 Screen recorder. April 30th, 2015 update

    Quote Originally Posted by Peter Porter View Post
    Fixed some issues, and cleaned up the code.

    Here's a preview of what I have in the works, using the same capture code above.

    Name:  Preview.png
Views: 9618
Size:  83.0 KB
    Hi Peter,

    Could you please send me the link to download latest MPEG-4 Screen recorder, I am not getting the sound file in your first project

    Thanks
    Vinod

  40. #40

    Thread Starter
    Fanatic Member Peter Porter's Avatar
    Join Date
    Jul 2013
    Posts
    532

    Re: VB.NET - MPEG-4 Screen recorder. April 30th, 2015 update

    vinodvin42, the polished looking version you quoted wont be available online as a project file. It has some extras, but it uses the same recording code as my older version.

    Have you downloaded the FFmpeg static build and placed it within this project's resources folder? It needs FFmpeg in order to record audio as well as video.

    The recorder was designed to work with older versions of FFmpeg below, but might work with the latest static builds now.
    32bit version
    64bit version

    If you have FFmpeg, the only other thing could be is that you don't have your system's Stereo Mix enabled.

    Enabling Stereo Mix for Windows Vista, 7 and 8
    * Right-click over the Speaker icon by the system clock then choose Recording Devices to open the Recording tab of "Sound".
    * Right-click Stereo Mix, and from it's dropdown menu, click Enable.

    Note (Vista, 7 and 8):
    If you don't see Stereo Mix, right click within the Recording tab window, then check "Show Disabled Devices".

    Enabling Stereo Mix for Windows XP
    * Click the Speaker icon by the system clock.
    * In the window that appears, choose Options then Properties.
    * In the next window, click the "Recording" radio button, then in "Show the following volume controls", click in the box for Stereo Mix, then "OK".
    Last edited by Peter Porter; Jul 31st, 2015 at 05:05 AM.

Page 1 of 2 12 LastLast

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width