c++ - programa - Grabador de pantalla
grabar pantalla windows 7 (6)
Este es el que uso con Delphi, se llama " Componente de cámara de pantalla profesional ". Es cierto que tuve que hacer algunos cambios para admitir versiones unicode (reemplace PChar con PAnsiChar, reemplace Char con AnsiChar).
Grabará felizmente en cualquier framerate que lo configure, codificará el video con cualquier códec que especifique (si lo deseo) y le permitirá especificar la región que desea grabar.
Viene con un proyecto de demostración también!
Ah, y es gratis / fuente abierta!
Estoy interesado en una biblioteca (para Windows) escrita en Delphi / Pascal o C ++ que me permite grabar (en un formato de video) la pantalla del escritorio, requisitos:
- debe poder especificar la velocidad de fotogramas, o al menos ser capaz de grabar @ 5fps;
- debe ser de código abierto o gratuito;
- el formato de salida podría ser casi cualquier, pero la calidad debe ser lo suficientemente buena como para poder leer el texto de la grabación;
ventajas, si es posible:
- opción para grabar sin colores (escala de grises);
- visualización múltiple consciente ;
- plataforma cruzada (Windows y Linux, otras plataformas también serían agradables, pero no necesarias);
Si, por casualidad, no explico algo bien, no dude en preguntar para poder reformular o dar más detalles, etc.
No he hecho esto antes, pero cuando busqué en Google (como estoy seguro de que tienes), me encontré con esto:
http://www.codeproject.com/KB/GDI/barry_s_screen_capture.aspx
Parece que debería hacer lo que está pidiendo razonablemente fácilmente (para Windows) y no tiene ninguna licencia asociada (como se confirma en la parte inferior). No creo que esté configurado como una biblioteca, pero estoy seguro de que podría vincular la interfaz a las funciones de muestra de WinCap en una con bastante facilidad.
Probablemente sea excesivo para sus necesidades, pero el componente del capturador de video de DataStead también puede registrar la actividad de la pantalla y guardar la salida como un archivo de video. Ver http://www.datastead.com/products/tvideograbber/overview.html . No estoy asociado con DataStead, pero he sido cliente por unos años y funciona muy bien.
Puede probar Windows Media Encoder (freeware, solo wmv / asf) o VLC (GPL, Win / OSX / Linux). Tenga en cuenta que las vistas "aceleradas por hardware" (Renderizado Direct3D y OpenGL, por ejemplo) no estarán disponibles, y se experimentarán algunas pérdidas de calidad debido a la compresión de video. Cuánto perderá dependerá de su configuración (códec, velocidad de bits, resolución, etc.)
Ejemplo: Cómo transmitir su escritorio usando 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}''
Puede encontrar más opciones en la documentación de VLC para guardar su transmisión como un archivo, por ejemplo.
FFMPEG admite la captura de pantalla (casting) y es multiplataforma.
FFmpeg se puede usar para capturar la pantalla.
Mire la demostración de video grabada en pantalla usando FFMPEG: https://www.youtube.com/watch?v=a31bBY3HuxE
Formato de contenedor: MP4
Códec: MPEG4
Siga los pasos para grabar la pantalla en video usando FFmpeg y otras bibliotecas.
Inicializar los registros requeridos
use x11grab (para Linux OS) en av_find_input_format
mencione la posición para capturar el video en la pantalla (por ejemplo, ": 0.0 + 10.250" en av_format_open_input)
Ahora vaya a la inicialización de los parámetros de video y la asignación de memoria.
comience a capturar los marcos y guárdelo en un archivo.
Finalmente, libera los recursos asignados una vez que hayas terminado.
El siguiente código está escrito en c ++ y utiliza el formato de video de la plataforma Linux (ubuntu) en formato 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 */