屏幕录像机

发布于 2024-12-18 13:16:42 字数 1539 浏览 2 评论 0原文

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

依 靠 2024-12-25 13:16:42

FFMPEG 支持屏幕捕获(投射)并且是跨平台的。

FFMPEG supports screen capturing(casting) and is cross platform.

爱要勇敢去追 2024-12-25 13:16:42

您可以尝试 Windows Media Encoder(免费软件,仅限 wmv/asf)或 VLC(GPL、Win/OSX/Linux)。请注意,“硬件加速”视图(例如 Direct3D 和 OpenGL 渲染)将不可用,并且由于视频压缩,将会出现一些质量损失。您丢失的数量取决于您的设置(编解码器、比特率、分辨率等)

示例:如何使用 VLC 流式传输桌面

vlc screen:// :screen-fps=30 :screen-caching=100 --sout '#transcode{vcodec=mp4v,vb=4096,acodec=mpga,ab=256,scale=1,width=1280,height=800}:rtp{dst=192.168.1.2,port=1234,access=udp,mux=ts}'

您可以在 VLC 文档,例如将流保存为文件。

You could try Windows Media Encoder (freeware, wmv/asf only) or VLC (GPL, Win/OSX/Linux). Be aware that "hardware accelerated" views (Direct3D & OpenGL rendering for example) will not be available, and some quality loss will be experienced due to video compression. How much you lose will depend on your settings (codec, bitrate, resolution, etc)

Example: How to Stream your Desktop using VLC

vlc screen:// :screen-fps=30 :screen-caching=100 --sout '#transcode{vcodec=mp4v,vb=4096,acodec=mpga,ab=256,scale=1,width=1280,height=800}:rtp{dst=192.168.1.2,port=1234,access=udp,mux=ts}'

You can find more options in VLC documentation, for saving your stream as a file for example.

能否归途做我良人 2024-12-25 13:16:42

这是我在 Delphi 中使用的一个,它被称为“专业屏幕摄像头组件”。不可否认,我必须进行一些更改才能支持 unicode 版本(将 PChar 替换为 PAnsiChar,将 Char 替换为 AnsiChar)。

它会很乐意以我设置的任何帧速率进行录制,使用我指定的任何编解码器(如果我想要的话)对视频进行编码,并允许您指定要录制的区域。

还附带一个演示项目!

哦,它是免费/开源的!

This is the one I use with Delphi, it's called "Professional Screen Camera Component". Admittedly I had to make some changes to support unicode versions (replace PChar with PAnsiChar, replace Char with AnsiChar).

It'll happily record away at whatever framerate I set it to, will encode the video with whatever codec I specify (if I want it to), and allows you to specify the region you wish to record.

Comes with a demo project too!

Oh, and it's free/open source!

拿命拼未来 2024-12-25 13:16:42

它可能超出了您的需求,但 DataStead 的视频采集器组件还可以记录屏幕活动并将输出保存为视频文件。请参阅http://www.datastead.com/products/tvideograbber/overview.html。我与 DataStead 没有任何关系,但我已经是几年前的客户了,而且效果很好。

It is probably overkill for your needs, but the video grabber component from DataStead can also record screen activity and save the output as video file. See http://www.datastead.com/products/tvideograbber/overview.html. I'm not associated with DataStead, but have been a customer for a few years and it works great.

霞映澄塘 2024-12-25 13:16:42

FFmpeg 可用于捕获屏幕。

观看使用 FFMPEG 录制的屏幕视频演示:https://www.youtube.com/watch?v=a31bBY3HuxE

容器格式 : MP4

编解码器 : MPEG4

按照以下步骤录制屏幕使用 FFmpeg 和其他库的视频。

  1. 初始化所需的寄存器

  2. 在 av_find_input_format 中使用 x11grab(适用于 linux 操作系统)

  3. 提及在屏幕中捕获视频的位置(例如 av_format_open_input 中的“:0.0+10,250”)

  4. 现在进行常规视频参数初始化和内存分配。

  5. 开始捕获帧并将其存储在文件中。

  6. 最后,完成后释放分配的资源!。

下面的代码是用c++编写的,使用linux(ubuntu)平台视频格式为mp4格式。

// sample code to record the computer screen !

      #ifndef SCREENRECORDER_H
      #define SCREENRECORDER_H

      #include <iostream>
      #include <cstdio>
      #include <cstdlib>
      #include <fstream>
      #include <cstring>
      #include <math.h>
      #include <string.h>

      #define __STDC_CONSTANT_MACROS

      //FFMPEG LIBRARIES
      extern "C"
      {
      #include "libavcodec/avcodec.h"
      #include "libavcodec/avfft.h"

      #include "libavdevice/avdevice.h"

      #include "libavfilter/avfilter.h"
      #include "libavfilter/avfiltergraph.h"
      #include "libavfilter/buffersink.h"
      #include "libavfilter/buffersrc.h"

      #include "libavformat/avformat.h"
      #include "libavformat/avio.h"

      // libav resample

      #include "libavutil/opt.h"
      #include "libavutil/common.h"
      #include "libavutil/channel_layout.h"
      #include "libavutil/imgutils.h"
      #include "libavutil/mathematics.h"
      #include "libavutil/samplefmt.h"
      #include "libavutil/time.h"
      #include "libavutil/opt.h"
      #include "libavutil/pixdesc.h"
      #include "libavutil/file.h"

      // lib swresample

      #include "libswscale/swscale.h"

      }



      class ScreenRecorder
      {
      private:
        AVInputFormat *pAVInputFormat;
        AVOutputFormat *output_format;

        AVCodecContext *pAVCodecContext;

        AVFormatContext *pAVFormatContext;

        AVFrame *pAVFrame;
        AVFrame *outFrame;

        AVCodec *pAVCodec;
        AVCodec *outAVCodec;

        AVPacket *pAVPacket;

        AVDictionary *options;

        AVOutputFormat *outAVOutputFormat;
        AVFormatContext *outAVFormatContext;
        AVCodecContext *outAVCodecContext;

        AVStream *video_st;
        AVFrame *outAVFrame;

        const char *dev_name;
        const char *output_file;

        double video_pts;

        int out_size;
        int codec_id;
        int value;
        int VideoStreamIndx;

      public:

        ScreenRecorder();
        ~ScreenRecorder();

        int openCamera();
        int init_outputfile();
        int collectFrames();

      };

      #endif


      using namespace std;

      ScreenRecorder::ScreenRecorder()
      {
        cout<<"\n\n Registering required functions...";
        av_register_all();
        avcodec_register_all();
        avdevice_register_all();
        cout<<"\n\n Registered successfully...";
      }

      ScreenRecorder::~ScreenRecorder()
      {

        avformat_close_input(&pAVFormatContext);
        if( !pAVFormatContext )
        {
        cout<<"\n\n1.Success : avformat_close_input()";
        }
        else
        {
        cout<<"\n\nError : avformat_close_input()";
        }

        avformat_free_context(pAVFormatContext);
        if( !pAVFormatContext )
        {
        cout<<"\n\n2.Success : avformat_free_context()";
        }
        else
        {
        cout<<"\n\nError : avformat_free_context()";
        }

      cout<<"\n\n---------------Successfully released all resources------------------\n\n\n";
      cout<<endl;
      cout<<endl;
      cout<<endl;
      }

      int ScreenRecorder::collectFrames()
      {
        int flag;
        int frameFinished;
      //when you decode a single packet, you still don't have information enough to have a frame [depending on the type of codec, some of them //you do], when you decode a GROUP of packets that represents a frame, then you have a picture! that's why frameFinished will let //you know you decoded enough to have a frame.

        int frame_index = 0;
        value = 0;

        pAVPacket = (AVPacket *)av_malloc(sizeof(AVPacket));
        av_init_packet(pAVPacket);

        pAVFrame = av_frame_alloc();
        if( !pAVFrame )
        {
         cout<<"\n\nError : av_frame_alloc()";
         return -1;
        }

        outFrame = av_frame_alloc();//Allocate an AVFrame and set its fields to default values.
        if( !outFrame )
        {
         cout<<"\n\nError : av_frame_alloc()";
         return -1;
        }

        int video_outbuf_size;
        int nbytes = av_image_get_buffer_size(outAVCodecContext->pix_fmt,outAVCodecContext->width,outAVCodecContext->height,32);
        uint8_t *video_outbuf = (uint8_t*)av_malloc(nbytes);
        if( video_outbuf == NULL )
        {
        cout<<"\n\nError : av_malloc()";
        }

        // Setup the data pointers and linesizes based on the specified image parameters and the provided array.
        value = av_image_fill_arrays( outFrame->data, outFrame->linesize, video_outbuf , AV_PIX_FMT_YUV420P, outAVCodecContext->width,outAVCodecContext->height,1 ); // returns : the size in bytes required for src
        if(value < 0)
        {
        cout<<"\n\nError : av_image_fill_arrays()";
        }

        SwsContext* swsCtx_ ;

        // Allocate and return swsContext.
        // a pointer to an allocated context, or NULL in case of error
        // Deprecated : Use sws_getCachedContext() instead.
        swsCtx_ = sws_getContext(pAVCodecContext->width,
                            pAVCodecContext->height,
                            pAVCodecContext->pix_fmt,
                            outAVCodecContext->width,
                    outAVCodecContext->height,
                            outAVCodecContext->pix_fmt,
                            SWS_BICUBIC, NULL, NULL, NULL);


      int ii = 0;
      int no_frames = 100;
      cout<<"\n\nEnter No. of Frames to capture : ";
      cin>>no_frames;

        AVPacket outPacket;
        int j = 0;

        int got_picture;

        while( av_read_frame( pAVFormatContext , pAVPacket ) >= 0 )
        {
        if( ii++ == no_frames )break;
            if(pAVPacket->stream_index == VideoStreamIndx)
            {
                value = avcodec_decode_video2( pAVCodecContext , pAVFrame , &frameFinished , pAVPacket );
                if( value < 0)
                {
                    cout<<"Error : avcodec_decode_video2()";
                }

                if(frameFinished)// Frame successfully decoded :)
                {
                    sws_scale(swsCtx_, pAVFrame->data, pAVFrame->linesize,0, pAVCodecContext->height, outFrame->data,outFrame->linesize);
                    av_init_packet(&outPacket);
                    outPacket.data = NULL;    // packet data will be allocated by the encoder
                    outPacket.size = 0;

                    avcodec_encode_video2(outAVCodecContext , &outPacket ,outFrame , &got_picture);

                    if(got_picture)
                    {
                        if(outPacket.pts != AV_NOPTS_VALUE)
                            outPacket.pts = av_rescale_q(outPacket.pts, video_st->codec->time_base, video_st->time_base);
                        if(outPacket.dts != AV_NOPTS_VALUE)
                            outPacket.dts = av_rescale_q(outPacket.dts, video_st->codec->time_base, video_st->time_base);

                        printf("Write frame %3d (size= %2d)\n", j++, outPacket.size/1000);
                        if(av_write_frame(outAVFormatContext , &outPacket) != 0)
                        {
                            cout<<"\n\nError : av_write_frame()";
                        }

                    av_packet_unref(&outPacket);
                    } // got_picture

                av_packet_unref(&outPacket);
                } // frameFinished

            }
        }// End of while-loop

        value = av_write_trailer(outAVFormatContext);
        if( value < 0)
        {
            cout<<"\n\nError : av_write_trailer()";
        }


      //THIS WAS ADDED LATER
      av_free(video_outbuf);

      }

      int ScreenRecorder::openCamera()
      {

        value = 0;
        options = NULL;
        pAVFormatContext = NULL;

        pAVFormatContext = avformat_alloc_context();//Allocate an AVFormatContext.

        pAVInputFormat = av_find_input_format("x11grab");
        value = avformat_open_input(&pAVFormatContext, ":0.0+10,250", pAVInputFormat, NULL);
        if(value != 0)
        {
           cout<<"\n\nError : avformat_open_input\n\nstopped...";
           return -1;
        }

        value = av_dict_set( &options,"framerate","30",0 );
        if(value < 0)
        {
          cout<<"\n\nError : av_dict_set(framerate , 30 , 0)";
          return -1;
        }

        value = av_dict_set( &options, "preset", "medium", 0 );
        if(value < 0)
        {
          cout<<"\n\nError : av_dict_set(preset , medium)";
              return -1;
        }

      //    value = avformat_find_stream_info(pAVFormatContext,NULL);
        if(value < 0)
        {
          cout<<"\n\nError : avformat_find_stream_info\nstopped...";
          return -1;
        }

        VideoStreamIndx = -1;

        for(int i = 0; i < pAVFormatContext->nb_streams; i++ ) // find video stream posistion/index.
        {
          if( pAVFormatContext->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO )
          {
             VideoStreamIndx = i;
             break;
          }

        } // End for-loop

        if( VideoStreamIndx == -1)
        {
          cout<<"\n\nError : VideoStreamIndx = -1";
          return -1;
        }

        // assign pAVFormatContext to VideoStreamIndx
        pAVCodecContext = pAVFormatContext->streams[VideoStreamIndx]->codec;

        pAVCodec = avcodec_find_decoder(pAVCodecContext->codec_id);
        if( pAVCodec == NULL )
        {
          cout<<"\n\nError : avcodec_find_decoder()";
          return -1;
        }

        value = avcodec_open2(pAVCodecContext , pAVCodec , NULL);//Initialize the AVCodecContext to use the given AVCodec.
        if( value < 0 )
        {
          cout<<"\n\nError : avcodec_open2()";
          return -1;
        }
      }

      int ScreenRecorder::init_outputfile()
      {
        outAVFormatContext = NULL;
        value = 0;
        output_file = "output.mp4";

        avformat_alloc_output_context2(&outAVFormatContext, NULL, NULL, output_file);
        if (!outAVFormatContext)
        {
            cout<<"\n\nError : avformat_alloc_output_context2()";
          return -1;
        }

      /*Returns the output format in the list of registered output formats which best matches the provided parameters, or returns NULL if there is no match.
      */
        output_format = av_guess_format(NULL, output_file ,NULL);
        if( !output_format )
        {
         cout<<"\n\nError : av_guess_format()";
         return -1;
        }

        video_st = avformat_new_stream(outAVFormatContext ,NULL);
        if( !video_st )
        {
            cout<<"\n\nError : avformat_new_stream()";
          return -1;
        }

        outAVCodecContext = avcodec_alloc_context3(outAVCodec);
        if( !outAVCodecContext )
        {
          cout<<"\n\nError : avcodec_alloc_context3()";
          return -1;
        }

        outAVCodecContext = video_st->codec;
        outAVCodecContext->codec_id = AV_CODEC_ID_MPEG4;// AV_CODEC_ID_MPEG4; // AV_CODEC_ID_H264 // AV_CODEC_ID_MPEG1VIDEO
        outAVCodecContext->codec_type = AVMEDIA_TYPE_VIDEO;
        outAVCodecContext->pix_fmt  = AV_PIX_FMT_YUV420P;
        outAVCodecContext->bit_rate = 400000; // 2500000
        outAVCodecContext->width = 1920;
        outAVCodecContext->height = 1080;
        outAVCodecContext->gop_size = 3;
        outAVCodecContext->max_b_frames = 2;
        outAVCodecContext->time_base.num = 1;
        outAVCodecContext->time_base.den = 30; // 15fps

        if (codec_id == AV_CODEC_ID_H264)
        {
         av_opt_set(outAVCodecContext->priv_data, "preset", "slow", 0);
        }

        outAVCodec = avcodec_find_encoder(AV_CODEC_ID_MPEG4);
        if( !outAVCodec )
        {
         cout<<"\n\nError : avcodec_find_encoder()";
         return -1;
        }

      // Some container formats (like MP4) require global headers to be present
      // Mark the encoder so that it behaves accordingly.

        if ( outAVFormatContext->oformat->flags & AVFMT_GLOBALHEADER)
        {
            outAVCodecContext->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
        }

        value = avcodec_open2(outAVCodecContext, outAVCodec, NULL);
        if( value < 0)
        {
            cout<<"\n\nError : avcodec_open2()";
            return -1;
        }

        if ( !(outAVFormatContext->flags & AVFMT_NOFILE) )
        {
         if( avio_open2(&outAVFormatContext->pb , output_file , AVIO_FLAG_WRITE ,NULL, NULL) < 0 )
         {
          cout<<"\n\nError : avio_open2()";
         }
        }



        if(!outAVFormatContext->nb_streams)
        {
            cout<<"\n\nError : Output file dose not contain any stream";
          return -1;
        }

        value = avformat_write_header(outAVFormatContext , &options);
        if(value < 0)
        {
            cout<<"\n\nError : avformat_write_header()";
            return -1;
        }

        cout<<"\n\nOutput file information :\n\n";
        av_dump_format(outAVFormatContext , 0 ,output_file ,1);
      }

      int main()
      {
        ScreenRecorder s_record;

        s_record.openCamera();
        s_record.init_outputfile();
        s_record.collectFrames();

        cout<<"\n\n---------EXIT_SUCCESS------------\n\n";

      return 0;
      }


      /* to compile the code : g++ -Wno-format-zero-length -Wno-write-strings -L/home/abdullah/ffmpeg_build/lib/ -L/usr/lib/x86_64-linux-gnu/ -I/home/abdullah/ffmpeg_build/include/ -o ScreenRecorder ScreenRecorder.cpp -lavdevice -lavfilter -lswscale -lavformat -lavcodec -lavutil -lswresample -lm -lva -lpthread -lvorbis -lvpx -lopus -lz -lpostproc -ldl -lfdk-aac -lmp3lame -lvorbisenc -lvorbisfile -lx264 -ltheora -lx265 -ltheoraenc -ltheoradec -ldl -lrt -lbz2 -lasound -lSDL -lSDLmain -lSDL_ttf -lfreetype -lass -llzma -lftgl -lperl -lcrypto -lxcb -lxcb-shm -lxcb-xfixes -lao -lxcb-shape -lfftw3 */

这是屏幕截图。
这是截图

完整的工作代码github链接

FFmpeg can be used to capture the screen.

watch the screen recorded video demo using FFMPEG : https://www.youtube.com/watch?v=a31bBY3HuxE

Container format : MP4

Codec : MPEG4

Follow the steps to record the screen in video using FFmpeg and other libraries.

  1. Initialize required registers

  2. use x11grab(for linux OS) in av_find_input_format

  3. mention the posistion to capture the video in screen (Eg. ":0.0+10,250" in av_format_open_input)

  4. Now go for regular video parameters initialization and memory allocation.

  5. start capturing the frames and store it in a file.

  6. Finally, release the allocated resources once completed !.

below code is written in c++ and uses linux(ubuntu) platform video format is in mp4 format.

// sample code to record the computer screen !

      #ifndef SCREENRECORDER_H
      #define SCREENRECORDER_H

      #include <iostream>
      #include <cstdio>
      #include <cstdlib>
      #include <fstream>
      #include <cstring>
      #include <math.h>
      #include <string.h>

      #define __STDC_CONSTANT_MACROS

      //FFMPEG LIBRARIES
      extern "C"
      {
      #include "libavcodec/avcodec.h"
      #include "libavcodec/avfft.h"

      #include "libavdevice/avdevice.h"

      #include "libavfilter/avfilter.h"
      #include "libavfilter/avfiltergraph.h"
      #include "libavfilter/buffersink.h"
      #include "libavfilter/buffersrc.h"

      #include "libavformat/avformat.h"
      #include "libavformat/avio.h"

      // libav resample

      #include "libavutil/opt.h"
      #include "libavutil/common.h"
      #include "libavutil/channel_layout.h"
      #include "libavutil/imgutils.h"
      #include "libavutil/mathematics.h"
      #include "libavutil/samplefmt.h"
      #include "libavutil/time.h"
      #include "libavutil/opt.h"
      #include "libavutil/pixdesc.h"
      #include "libavutil/file.h"

      // lib swresample

      #include "libswscale/swscale.h"

      }



      class ScreenRecorder
      {
      private:
        AVInputFormat *pAVInputFormat;
        AVOutputFormat *output_format;

        AVCodecContext *pAVCodecContext;

        AVFormatContext *pAVFormatContext;

        AVFrame *pAVFrame;
        AVFrame *outFrame;

        AVCodec *pAVCodec;
        AVCodec *outAVCodec;

        AVPacket *pAVPacket;

        AVDictionary *options;

        AVOutputFormat *outAVOutputFormat;
        AVFormatContext *outAVFormatContext;
        AVCodecContext *outAVCodecContext;

        AVStream *video_st;
        AVFrame *outAVFrame;

        const char *dev_name;
        const char *output_file;

        double video_pts;

        int out_size;
        int codec_id;
        int value;
        int VideoStreamIndx;

      public:

        ScreenRecorder();
        ~ScreenRecorder();

        int openCamera();
        int init_outputfile();
        int collectFrames();

      };

      #endif


      using namespace std;

      ScreenRecorder::ScreenRecorder()
      {
        cout<<"\n\n Registering required functions...";
        av_register_all();
        avcodec_register_all();
        avdevice_register_all();
        cout<<"\n\n Registered successfully...";
      }

      ScreenRecorder::~ScreenRecorder()
      {

        avformat_close_input(&pAVFormatContext);
        if( !pAVFormatContext )
        {
        cout<<"\n\n1.Success : avformat_close_input()";
        }
        else
        {
        cout<<"\n\nError : avformat_close_input()";
        }

        avformat_free_context(pAVFormatContext);
        if( !pAVFormatContext )
        {
        cout<<"\n\n2.Success : avformat_free_context()";
        }
        else
        {
        cout<<"\n\nError : avformat_free_context()";
        }

      cout<<"\n\n---------------Successfully released all resources------------------\n\n\n";
      cout<<endl;
      cout<<endl;
      cout<<endl;
      }

      int ScreenRecorder::collectFrames()
      {
        int flag;
        int frameFinished;
      //when you decode a single packet, you still don't have information enough to have a frame [depending on the type of codec, some of them //you do], when you decode a GROUP of packets that represents a frame, then you have a picture! that's why frameFinished will let //you know you decoded enough to have a frame.

        int frame_index = 0;
        value = 0;

        pAVPacket = (AVPacket *)av_malloc(sizeof(AVPacket));
        av_init_packet(pAVPacket);

        pAVFrame = av_frame_alloc();
        if( !pAVFrame )
        {
         cout<<"\n\nError : av_frame_alloc()";
         return -1;
        }

        outFrame = av_frame_alloc();//Allocate an AVFrame and set its fields to default values.
        if( !outFrame )
        {
         cout<<"\n\nError : av_frame_alloc()";
         return -1;
        }

        int video_outbuf_size;
        int nbytes = av_image_get_buffer_size(outAVCodecContext->pix_fmt,outAVCodecContext->width,outAVCodecContext->height,32);
        uint8_t *video_outbuf = (uint8_t*)av_malloc(nbytes);
        if( video_outbuf == NULL )
        {
        cout<<"\n\nError : av_malloc()";
        }

        // Setup the data pointers and linesizes based on the specified image parameters and the provided array.
        value = av_image_fill_arrays( outFrame->data, outFrame->linesize, video_outbuf , AV_PIX_FMT_YUV420P, outAVCodecContext->width,outAVCodecContext->height,1 ); // returns : the size in bytes required for src
        if(value < 0)
        {
        cout<<"\n\nError : av_image_fill_arrays()";
        }

        SwsContext* swsCtx_ ;

        // Allocate and return swsContext.
        // a pointer to an allocated context, or NULL in case of error
        // Deprecated : Use sws_getCachedContext() instead.
        swsCtx_ = sws_getContext(pAVCodecContext->width,
                            pAVCodecContext->height,
                            pAVCodecContext->pix_fmt,
                            outAVCodecContext->width,
                    outAVCodecContext->height,
                            outAVCodecContext->pix_fmt,
                            SWS_BICUBIC, NULL, NULL, NULL);


      int ii = 0;
      int no_frames = 100;
      cout<<"\n\nEnter No. of Frames to capture : ";
      cin>>no_frames;

        AVPacket outPacket;
        int j = 0;

        int got_picture;

        while( av_read_frame( pAVFormatContext , pAVPacket ) >= 0 )
        {
        if( ii++ == no_frames )break;
            if(pAVPacket->stream_index == VideoStreamIndx)
            {
                value = avcodec_decode_video2( pAVCodecContext , pAVFrame , &frameFinished , pAVPacket );
                if( value < 0)
                {
                    cout<<"Error : avcodec_decode_video2()";
                }

                if(frameFinished)// Frame successfully decoded :)
                {
                    sws_scale(swsCtx_, pAVFrame->data, pAVFrame->linesize,0, pAVCodecContext->height, outFrame->data,outFrame->linesize);
                    av_init_packet(&outPacket);
                    outPacket.data = NULL;    // packet data will be allocated by the encoder
                    outPacket.size = 0;

                    avcodec_encode_video2(outAVCodecContext , &outPacket ,outFrame , &got_picture);

                    if(got_picture)
                    {
                        if(outPacket.pts != AV_NOPTS_VALUE)
                            outPacket.pts = av_rescale_q(outPacket.pts, video_st->codec->time_base, video_st->time_base);
                        if(outPacket.dts != AV_NOPTS_VALUE)
                            outPacket.dts = av_rescale_q(outPacket.dts, video_st->codec->time_base, video_st->time_base);

                        printf("Write frame %3d (size= %2d)\n", j++, outPacket.size/1000);
                        if(av_write_frame(outAVFormatContext , &outPacket) != 0)
                        {
                            cout<<"\n\nError : av_write_frame()";
                        }

                    av_packet_unref(&outPacket);
                    } // got_picture

                av_packet_unref(&outPacket);
                } // frameFinished

            }
        }// End of while-loop

        value = av_write_trailer(outAVFormatContext);
        if( value < 0)
        {
            cout<<"\n\nError : av_write_trailer()";
        }


      //THIS WAS ADDED LATER
      av_free(video_outbuf);

      }

      int ScreenRecorder::openCamera()
      {

        value = 0;
        options = NULL;
        pAVFormatContext = NULL;

        pAVFormatContext = avformat_alloc_context();//Allocate an AVFormatContext.

        pAVInputFormat = av_find_input_format("x11grab");
        value = avformat_open_input(&pAVFormatContext, ":0.0+10,250", pAVInputFormat, NULL);
        if(value != 0)
        {
           cout<<"\n\nError : avformat_open_input\n\nstopped...";
           return -1;
        }

        value = av_dict_set( &options,"framerate","30",0 );
        if(value < 0)
        {
          cout<<"\n\nError : av_dict_set(framerate , 30 , 0)";
          return -1;
        }

        value = av_dict_set( &options, "preset", "medium", 0 );
        if(value < 0)
        {
          cout<<"\n\nError : av_dict_set(preset , medium)";
              return -1;
        }

      //    value = avformat_find_stream_info(pAVFormatContext,NULL);
        if(value < 0)
        {
          cout<<"\n\nError : avformat_find_stream_info\nstopped...";
          return -1;
        }

        VideoStreamIndx = -1;

        for(int i = 0; i < pAVFormatContext->nb_streams; i++ ) // find video stream posistion/index.
        {
          if( pAVFormatContext->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO )
          {
             VideoStreamIndx = i;
             break;
          }

        } // End for-loop

        if( VideoStreamIndx == -1)
        {
          cout<<"\n\nError : VideoStreamIndx = -1";
          return -1;
        }

        // assign pAVFormatContext to VideoStreamIndx
        pAVCodecContext = pAVFormatContext->streams[VideoStreamIndx]->codec;

        pAVCodec = avcodec_find_decoder(pAVCodecContext->codec_id);
        if( pAVCodec == NULL )
        {
          cout<<"\n\nError : avcodec_find_decoder()";
          return -1;
        }

        value = avcodec_open2(pAVCodecContext , pAVCodec , NULL);//Initialize the AVCodecContext to use the given AVCodec.
        if( value < 0 )
        {
          cout<<"\n\nError : avcodec_open2()";
          return -1;
        }
      }

      int ScreenRecorder::init_outputfile()
      {
        outAVFormatContext = NULL;
        value = 0;
        output_file = "output.mp4";

        avformat_alloc_output_context2(&outAVFormatContext, NULL, NULL, output_file);
        if (!outAVFormatContext)
        {
            cout<<"\n\nError : avformat_alloc_output_context2()";
          return -1;
        }

      /*Returns the output format in the list of registered output formats which best matches the provided parameters, or returns NULL if there is no match.
      */
        output_format = av_guess_format(NULL, output_file ,NULL);
        if( !output_format )
        {
         cout<<"\n\nError : av_guess_format()";
         return -1;
        }

        video_st = avformat_new_stream(outAVFormatContext ,NULL);
        if( !video_st )
        {
            cout<<"\n\nError : avformat_new_stream()";
          return -1;
        }

        outAVCodecContext = avcodec_alloc_context3(outAVCodec);
        if( !outAVCodecContext )
        {
          cout<<"\n\nError : avcodec_alloc_context3()";
          return -1;
        }

        outAVCodecContext = video_st->codec;
        outAVCodecContext->codec_id = AV_CODEC_ID_MPEG4;// AV_CODEC_ID_MPEG4; // AV_CODEC_ID_H264 // AV_CODEC_ID_MPEG1VIDEO
        outAVCodecContext->codec_type = AVMEDIA_TYPE_VIDEO;
        outAVCodecContext->pix_fmt  = AV_PIX_FMT_YUV420P;
        outAVCodecContext->bit_rate = 400000; // 2500000
        outAVCodecContext->width = 1920;
        outAVCodecContext->height = 1080;
        outAVCodecContext->gop_size = 3;
        outAVCodecContext->max_b_frames = 2;
        outAVCodecContext->time_base.num = 1;
        outAVCodecContext->time_base.den = 30; // 15fps

        if (codec_id == AV_CODEC_ID_H264)
        {
         av_opt_set(outAVCodecContext->priv_data, "preset", "slow", 0);
        }

        outAVCodec = avcodec_find_encoder(AV_CODEC_ID_MPEG4);
        if( !outAVCodec )
        {
         cout<<"\n\nError : avcodec_find_encoder()";
         return -1;
        }

      // Some container formats (like MP4) require global headers to be present
      // Mark the encoder so that it behaves accordingly.

        if ( outAVFormatContext->oformat->flags & AVFMT_GLOBALHEADER)
        {
            outAVCodecContext->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
        }

        value = avcodec_open2(outAVCodecContext, outAVCodec, NULL);
        if( value < 0)
        {
            cout<<"\n\nError : avcodec_open2()";
            return -1;
        }

        if ( !(outAVFormatContext->flags & AVFMT_NOFILE) )
        {
         if( avio_open2(&outAVFormatContext->pb , output_file , AVIO_FLAG_WRITE ,NULL, NULL) < 0 )
         {
          cout<<"\n\nError : avio_open2()";
         }
        }



        if(!outAVFormatContext->nb_streams)
        {
            cout<<"\n\nError : Output file dose not contain any stream";
          return -1;
        }

        value = avformat_write_header(outAVFormatContext , &options);
        if(value < 0)
        {
            cout<<"\n\nError : avformat_write_header()";
            return -1;
        }

        cout<<"\n\nOutput file information :\n\n";
        av_dump_format(outAVFormatContext , 0 ,output_file ,1);
      }

      int main()
      {
        ScreenRecorder s_record;

        s_record.openCamera();
        s_record.init_outputfile();
        s_record.collectFrames();

        cout<<"\n\n---------EXIT_SUCCESS------------\n\n";

      return 0;
      }


      /* to compile the code : g++ -Wno-format-zero-length -Wno-write-strings -L/home/abdullah/ffmpeg_build/lib/ -L/usr/lib/x86_64-linux-gnu/ -I/home/abdullah/ffmpeg_build/include/ -o ScreenRecorder ScreenRecorder.cpp -lavdevice -lavfilter -lswscale -lavformat -lavcodec -lavutil -lswresample -lm -lva -lpthread -lvorbis -lvpx -lopus -lz -lpostproc -ldl -lfdk-aac -lmp3lame -lvorbisenc -lvorbisfile -lx264 -ltheora -lx265 -ltheoraenc -ltheoradec -ldl -lrt -lbz2 -lasound -lSDL -lSDLmain -lSDL_ttf -lfreetype -lass -llzma -lftgl -lperl -lcrypto -lxcb -lxcb-shm -lxcb-xfixes -lao -lxcb-shape -lfftw3 */

Here's the screenshot.
Here's the screenshot

complete working code in github link:

香草可樂 2024-12-25 13:16:42

我自己以前没有这样做过,但是当我用谷歌搜索时(我相信你已经这样做了),我遇到了这个:

http://www.codeproject.com/KB/GDI/barry_s_screen_capture.aspx

看起来它应该很容易地完成您所要求的任务(对于Windows),并且没有与之关联的许可证(如底部所确认)。我不相信它被设置为一个库,但我确信您可以轻松地将示例 WinCap 函数的接口绑定到一个库中。

I haven't done this myself before, but when I googled around (as I'm sure you have), I ran into this:

http://www.codeproject.com/KB/GDI/barry_s_screen_capture.aspx

It looks as if it should do what you're asking reasonably easily (for Windows), and it has no license associated with it (as confirmed at the bottom). I don't believe its set up as a library, but I'm sure you could bind the interface to the sample WinCap functions into one with reasonable ease.

○闲身 2024-12-25 13:16:42

使用屏幕捕获精简版
https://github.com/smasherprog/screen_capture_lite

这是一个 C++ 库,跨平台

use screen capture lite
https://github.com/smasherprog/screen_capture_lite

This is a C++ library and cross-platform

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文