C语言实现为无声avi视频添加wave音乐
作者:乐山劲松
这篇文章主要为大家详细介绍了C语言如何实现为无声avi视频添加wave音乐,文中的示例代码讲解详细,具有一定的参考价值,感兴趣的小伙伴可以了解一下
编程中发现,头文件结构中很多参数要求很不严格,只有少数几个很重要,
其实,这个程序就是为后期的用摄像头录像,麦克风录音作准备的,此程序用的音频我就是用麦克风录制的。
现在此程序生成的avi 可以被deepin的 自带视频播放软件播放了。
我理解,单位时间内,视频和音频交叉的数据的播放时间要相等。单位内音频和视频可以多次交叉,也可交叉一次。
每一段交叉的音频视频数据前必须要要加数据类型标识xxdc,xxwb和数据长度。告诉播放器下面的数据是什麽类型,有多长。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <malloc.h>
#include <wait.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
static int ap;
static int at;
static int nframe = 0;
static unsigned int vzj = 0;
static unsigned int azj = 0;
//下面7个参数必须要先定义
#define zwidth 720
#define zheigth 496
#define zvrate 30 //video 帧率
#define channal 2 //audio 频道数
#define zarate 44100 //audio 采样率
#define bitper 16 //audio 采样宽度
#define vbitper 24 //video 采样宽度
int main(void) {
struct file {
struct riff {
char id[4];
unsigned int size;
char type[4];
struct hdrl {
char id[4];
unsigned int size;
unsigned char type[4];
struct avih {
unsigned char id[4]; //块ID,固定为avih
unsigned int size; //块大小,等于struct avi_avih_chunk去掉id和size的大小
unsigned int us_per_frame; //视频帧间隔时间(以微秒为单位)
unsigned int max_bytes_per_sec; //AVI文件的最大数据率
unsigned int padding; //设为0即可
unsigned int flags; //AVI文件全局属性,如是否含有索引块、音视频数据是否交叉存储等
unsigned int total_frames; //总帧数
unsigned int init_frames; //为交互格式指定初始帧数(非交互格式应该指定为0)
unsigned int streams; //文件包含的流的个数,仅有视频流时为1
unsigned int suggest_buff_size; //指定读取本文件建议使用的缓冲区大小,通常为存储一桢图像
unsigned int width; //视频主窗口宽度(单位:像素)
unsigned int height; //视频主窗口高度(单位:像素)
unsigned int reserved[4]; //保留段,设为0即可
} av;
struct strl {
unsigned char id[4]; //块ID,固定为LIST
unsigned int size; //块大小,等于struct avi_strl_list去掉id和size的大小
unsigned char type[4]; //strl
struct strh1 {
unsigned char id[4]; //块ID,固定为strh
unsigned int size; //块大小,等于struct avi_strh_chunk去掉id和size的大小
unsigned char stream_type[4]; //流的类型,vids表示视频流,auds表示音频流
unsigned char codec[4]; //指定处理这个流需要的解码器,如JPEG
unsigned int flags; //标记,如是否允许这个流输出、调色板是否变化等,一般设为0即可
unsigned short priority; //流的优先级,视频流设为0即可
unsigned short language; //音频语言代号,视频流设为0即可
unsigned int init_frames; //为交互格式指定初始帧数(非交互格式应该指定为0)
unsigned int scale; //
unsigned int rate; //对于视频流,rate / scale = 帧率fps
unsigned int start; //对于视频流,设为0即可
unsigned int length; //对于视频流,length即总帧数
unsigned int suggest_buff_size; //读取这个流数据建议使用的缓冲区大小
unsigned int quality; //流数据的质量指标
unsigned int sample_size; //音频采样大小,视频流设为0即可
short left; //这个流在视频主窗口中的显示位置,设为{0,0,width,height}即可
short top;
short right;
short bottom;
} sh1;
struct strf1 {
unsigned char id[4]; //块ID,固定为strf
unsigned int size; //块大小,等于struct avi_strf_chunk去掉id和size的大小
//_BITMAPINFOHEADER 结构
int size1; // 指定结构所需的字节数。=size
unsigned int width; //指定位图的宽度(以像素为单位)。
unsigned int height; //指定位图的高度(以像素为单位)
unsigned short planes; //指定目标设备的平面数。 此值必须设置为 1。
unsigned short bitcount; //每个像素占的位数,只能是1、4、8、16、24和32中的一个
unsigned char compression[4]; //指定压缩的自下而上位图的压缩类型
unsigned int image_size; //指定图像的大小(以字节为单位),等于width * height * bitcount / 8
unsigned int x_pixels_per_meter; //显示设备的水平分辨率,设为0即可
unsigned int y_pixels_per_meter; //显示设备的垂直分辨率,设为0即可
unsigned int num_colors; //含义不清楚,设为0即可
unsigned int imp_colors; //含义不清楚,设为0即可
} sf1;
} sl1;
struct strl2 {
unsigned char id[4]; //块ID,固定为LIST
unsigned int size; //块大小,等于struct avi_strl_list去掉id和size的大小
unsigned char type[4]; //strl
struct strh2 {
unsigned char id[4]; //块ID,固定为strh
unsigned int size; //块大小,等于struct avi_strh_chunk去掉id和size的大小
unsigned char stream_type[4]; //流的类型,vids表示视频流,auds表示音频流
unsigned char codec[4]; //指定处理这个流需要的解码器,如JPEG
unsigned int flags; //标记,如是否允许这个流输出、调色板是否变化等,一般设为0即可
unsigned short priority; //流的优先级,视频流设为0即可
unsigned short language; //音频语言代号,视频流设为0即可
unsigned int init_frames; //为交互格式指定初始帧数(非交互格式应该指定为0)
unsigned int scale; //
unsigned int rate; //对于视频流,rate / scale = 帧率fps
unsigned int start; //对于视频流,设为0即可
unsigned int length; //对于视频流,length即总帧数
unsigned int suggest_buff_size; //读取这个流数据建议使用的缓冲区大小
unsigned int quality; //流数据的质量指标
unsigned int sample_size; //音频采样大小,视频流设为0即可
short left; //这个流在视频主窗口中的显示位置,设为{0,0,width,height}即可
short top;
short right;
short bottom;
} sh2;
struct strf2 {
char id[4]; //strf
int size;
short wFormatTag; //波形音频格式类型,格式标记在 Microsoft Corporation 中注册,用于许多压缩算法,
short nChannels; //声道数 85= WAVE_FORMAT_PCM
int nSamplesPerSec; //采样率,以每秒样本数 (赫) ,常见值为 8.0 kHz、11.025 kHz、22.05 kHz 和 44.1 kHz
int nAvgBytesPerSec; //格式标记所需的平均数据传输速率(以字节/秒为单位)=nsam*nblock
short nBlockAlign; //阻止对齐(以字节为单位),nBlockAlign 必须等于 nChannels 和 wBitsPerSample 的乘积除以 8 (位/字节)
short wBitsPerSample;// 如果 wFormatTag WAVE_FORMAT_PCM,则 wBitsPerSample 应等于 8 或 16
short biSize; //追加到 WAVEFORMATEX 结构末尾的额外格式信息的大小(以字节为单位)
} sf2;
} sl2;
} hd;
struct movi {
char id[4];
unsigned int size;
char type[4];
} mo;
} ri;
} head;
FILE *fo = fopen("/home/wjs/Videos/demo.avi", "w+b"); //生成avi
FILE *f = fopen("/home/wjs/Videos/tra_mjpg.avi", "r+b"); //无声视频文件
FILE *af = fopen("/home/wjs/Music/15s.wav", "r+b"); //wav 文件
fseek(fo, sizeof(head), SEEK_SET);
if (f == NULL) {
puts("file_in error");
exit(-1);
}
if (af == NULL) {
puts("file2_in error");
exit(-1);
}
fseek(f, 0, SEEK_END);
int flen = ftell(f);
fseek(f, 0, SEEK_SET);
fseek(af, 0, SEEK_END);
int aflen = ftell(af);
fseek(af, 0, SEEK_SET);
int tf = fileno(f);
int taf = fileno(af);
char *mf = mmap(NULL, flen, PROT_READ | PROT_WRITE, MAP_SHARED, tf, 0);
char *maf = mmap(NULL, aflen, PROT_READ | PROT_WRITE, MAP_SHARED, taf, 0);
for (int a = 0; a < aflen; a++) {
if ((maf[a] == 'd') && (maf[a + 1] == 'a') && (maf[a + 2] == 't') && (maf[a + 3] == 'a')) {
ap = a + 4 + 4;
at = ap;
}
}
int t = 0;
while (t < flen) {
int n = 0;
while ((n <zvrate) && (t < flen)) {
if ((mf[t] == '0') && (mf[t + 1] == '0') && (mf[t + 2] == 'd') && (mf[t + 3]) == 'c') {
char c00dc[] = {'0', '0', 'd', 'c'};
fwrite(c00dc, 4, 1, fo);
fwrite(&mf[t + 4], 4, 1, fo); //写长度
int dx = 0;
memcpy(&dx, &mf[t + 4], 4);
fwrite(&mf[t + 8], dx, 1, fo); //写数据
vzj = vzj + 8 + dx;
n++;
t++;
nframe++;
} else {
t++;
}
}
//------------------------ 以一秒为单位,视频,音频数据交叉一次------------------------------------------------
char c01wb[] = {'0', '1', 'w', 'b'};
fwrite(c01wb, 4, 1, fo);
int h=channal*zarate*bitper/8;
fwrite(&h,4,1,fo);
azj = azj + 8;
fwrite(&maf[ap],h, 1, fo); //写audio数据
ap = ap +h;
azj = azj +h;
}
//----------------------------------------------
typedef struct file File;
File ffile = {
{
//riff
{'R', 'I', 'F', 'F'},
vzj + azj + 8,
{'A', 'V', 'I', ' '},
//hdrl
{
{'L', 'I', 'S', 'T'},
sizeof(head.ri.hd) - 8,
{'s', 't', 'r', 'l'},
//avih
{
{'a', 'v', 'i', 'h'},
sizeof(head.ri.hd.av) - 8,
1000000/zvrate,
zwidth*zheigth*vbitper*zvrate,
0, 0, nframe,0,
2, //audio + video 流总数
zwidth*zheigth*vbitper,
zwidth,zheigth, {0, 0, 0, 0}
},
//strl1
{
{'L', 'I', 'S', 'T'},
sizeof(head.ri.hd.sl1) - 8,
{'s', 't', 'r', 'l'},
{
//strh1
{'s', 't', 'r', 'h'},
sizeof(head.ri.hd.sl1.sh1) - 8,
{'v', 'i', 'd', 's'}, //代表视频
{'M', 'J', 'P', 'G'}, //图像格式
0, 0, 0, 0,
1,zvrate,
0, nframe,
zwidth*zheigth*vbitper*zvrate,
10000, 0,
0, 0,zwidth,zheigth
},
{
//strf1
{'s', 't', 'r', 'f'},
sizeof(head.ri.hd.sl1.sf1) - 8,
sizeof(head.ri.hd.sl1.sf1) - 8,
zwidth,zheigth, 1,
vbitper,
{'M', 'J', 'P', 'G'}, //图像格式
zwidth*zheigth*vbitper/8,
0, 0, 0, 0
}
},
//strl2
{
{'L', 'I', 'S', 'T'},
sizeof(head.ri.hd.sl2) - 8,
{'s', 't', 'r', 'l'},
{
//strh2
{'s', 't', 'r', 'h'},
sizeof(head.ri.hd.sl2.sh2) - 8,
{'a', 'u', 'd', 's'}, //代表声音
{0, 0, 0, 0},
0, 0, 0, 0,
1,zarate, //这个帧率会影响图像的帧率
0, 0,channal*zarate*bitper/8, 10000, zarate,
0, 0, 0, 0
},
{
//strf2
{'s', 't', 'r', 'f'},
sizeof(head.ri.hd.sl2.sf2) - 8,
1,channal,zarate,zarate*channal*bitper/8,channal*bitper/8,bitper, 0
}
}
},
//movi
{
{'L', 'I', 'S', 'T'},
// movisize,
vzj,
{'m', 'o', 'v', 'i'}
}
}
};
fseek(fo, 0, SEEK_SET);
fwrite(&ffile, sizeof(ffile), 1, fo);
//-----------------------------------------
fclose(fo);
puts("over");
return 0;
}附 查看avi文件参数:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <malloc.h>
#include <wait.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
int main(void){
struct file{
struct riff{
char id[4];
unsigned int size;
char type[4];
struct hdrl{
char id[4];
unsigned int size;
unsigned char type[4];
struct avih{
unsigned char id[4]; //块ID,固定为avih
unsigned int size; //块大小,等于struct avi_avih_chunk去掉id和size的大小
unsigned int us_per_frame; //视频帧间隔时间(以微秒为单位)
unsigned int max_bytes_per_sec; //AVI文件的最大数据率
unsigned int padding; //设为0即可
unsigned int flags; //AVI文件全局属性,如是否含有索引块、音视频数据是否交叉存储等
unsigned int total_frames; //总帧数
unsigned int init_frames; //为交互格式指定初始帧数(非交互格式应该指定为0)
unsigned int streams; //文件包含的流的个数,仅有视频流时为1
unsigned int suggest_buff_size; //指定读取本文件建议使用的缓冲区大小,通常为存储一桢图像
unsigned int width; //视频主窗口宽度(单位:像素)
unsigned int height; //视频主窗口高度(单位:像素)
unsigned int reserved[4]; //保留段,设为0即可
}av;
struct strl{
unsigned char id[4]; //块ID,固定为LIST
unsigned int size; //块大小,等于struct avi_strl_list去掉id和size的大小
unsigned char type[4]; //strl
struct strh1{
unsigned char id[4]; //块ID,固定为strh
unsigned int size; //块大小,等于struct avi_strh_chunk去掉id和size的大小
unsigned char stream_type[4]; //流的类型,vids表示视频流,auds表示音频流
unsigned char codec[4]; //指定处理这个流需要的解码器,如JPEG
unsigned int flags; //标记,如是否允许这个流输出、调色板是否变化等,一般设为0即可
unsigned short priority; //流的优先级,视频流设为0即可
unsigned short language; //音频语言代号,视频流设为0即可
unsigned int init_frames; //为交互格式指定初始帧数(非交互格式应该指定为0)
unsigned int scale; //
unsigned int rate; //对于视频流,rate / scale = 帧率fps
unsigned int start; //对于视频流,设为0即可
unsigned int length; //对于视频流,length即总帧数
unsigned int suggest_buff_size; //读取这个流数据建议使用的缓冲区大小
unsigned int quality; //流数据的质量指标
unsigned int sample_size; //音频采样大小,视频流设为0即可
short left; //这个流在视频主窗口中的显示位置,设为{0,0,width,height}即可
short top;
short right;
short bottom;
}sh1;
struct strf1{
unsigned char id[4]; //块ID,固定为strf
unsigned int size; //块大小,等于struct avi_strf_chunk去掉id和size的大小
//_BITMAPINFOHEADER 结构
int size1; // 指定结构所需的字节数。=size
unsigned int width; //指定位图的宽度(以像素为单位)。
unsigned int height; //指定位图的高度(以像素为单位)
unsigned short planes; //指定目标设备的平面数。 此值必须设置为 1。
unsigned short bitcount; //每个像素占的位数,只能是1、4、8、16、24和32中的一个
unsigned char compression[4]; //指定压缩的自下而上位图的压缩类型
unsigned int image_size; //指定图像的大小(以字节为单位),等于width * height * bitcount / 8
unsigned int x_pixels_per_meter; //显示设备的水平分辨率,设为0即可
unsigned int y_pixels_per_meter; //显示设备的垂直分辨率,设为0即可
unsigned int num_colors; //含义不清楚,设为0即可
unsigned int imp_colors; //含义不清楚,设为0即可
}sf1;
}sl1;
struct strl2{
unsigned char id[4]; //块ID,固定为LIST
unsigned int size; //块大小,等于struct avi_strl_list去掉id和size的大小
unsigned char type[4]; //strl
struct strh2{
unsigned char id[4]; //块ID,固定为strh
unsigned int size; //块大小,等于struct avi_strh_chunk去掉id和size的���小
unsigned char stream_type[4]; //流的类型,vids表示视频流,auds表示音频流
unsigned char codec[4]; //指定处理这个流需要的解码器,如JPEG
unsigned int flags; //标记,如是否允许这个流输出、调色板是否变化等,一般设为0即可
unsigned short priority; //流的优先级,视频流设为0即可
unsigned short language; //音频语言代号,视频流设为0即可
unsigned int init_frames; //为交互格式指定初始帧数(非交互格式应该指定为0)
unsigned int scale; //
unsigned int rate; //对于视频流,rate / scale = 帧率fps
unsigned int start; //对于视频流,设为0即可
unsigned int length; //对于视频流,length即总帧数
unsigned int suggest_buff_size; //读取这个流数据建议使用的缓冲区大小
unsigned int quality; //流数据的质量指标
unsigned int sample_size; //音频采样大小,视频流设为0即可
short left; //这个流在视频主窗口中的显示位置,设为{0,0,width,height}即可
short top;
short right;
short bottom;
}sh2;
struct strf2{
char id[4]; //strf
int size;
short wFormatTag; //波形音频格式类型,格式标记在 Microsoft Corporation 中注册,用于许多压缩算法,
short nChannels; //声道数 85= WAVE_FORMAT_PCM
int nSamplesPerSec; //采样率,以每秒样本数 (赫) ,常见值为 8.0 kHz、11.025 kHz、22.05 kHz 和 44.1 kHz
int nAvgBytesPerSec; //格式标记所需的平均数据传输速率(以字节/秒为单位)=nsam*nblock
short nBlockAlign; //阻止对齐(以字节为单位),nBlockAlign 必须等于 nChannels 和 wBitsPerSample 的乘积除以 8 (位/字节)
short wBitsPerSample;// 如果 wFormatTag WAVE_FORMAT_PCM,则 wBitsPerSample 应等于 8 或 16
short biSize; //追加到 WAVEFORMATEX 结构末尾的额外格式信息的大小(以字节为单位)
}sf2;
}sl2;
}hd;
struct movi{
char id[4];
unsigned int size;
char type[4];
}mo;
}ri;
}head;
FILE *f=fopen("/home/wzpc/Videos/2vuy.avi","rb");
if(f==NULL){
puts("file in error");
exit(-1);
}
fseek(f,0,SEEK_END);
int len=ftell(f);
fseek(f,0,SEEK_SET);
int fd=fileno(f);
char *m=mmap(NULL,len,PROT_READ,MAP_SHARED,fd,0);
memcpy(&head,&m[0],sizeof(head));
//avih
printf("-----------avih--------------\n");
printf("avih_id: %s\n",head.ri.hd.av.id);
printf("size: %d\n",head.ri.hd.av.size);
printf("us_per_frame: %d\n",head.ri.hd.av.us_per_frame);
printf("max_bytes_per_sec: %d\n",head.ri.hd.av.max_bytes_per_sec);
printf("paddind: %d\n",head.ri.hd.av.padding);
printf("flags: %d\n",head.ri.hd.av.flags);
printf("total_frames: %d\n",head.ri.hd.av.total_frames);
printf("init_frame: %d\n",head.ri.hd.av.init_frames);
printf("stream: %d\n",head.ri.hd.av.streams);
printf("suggest_buff_size: %d\n",head.ri.hd.av.suggest_buff_size);
printf("width: %d\n",head.ri.hd.av.width);
printf("height: %d\n",head.ri.hd.av.height);
//strh
printf("-----------video strh--------------\n");
printf("strh_id: %s\n",head.ri.hd.sl1.sh1.id);
printf("size: %d\n",head.ri.hd.sl1.sh1.size);
printf("stream_type: %s\n",head.ri.hd.sl1.sh1.stream_type);
printf("codes: %s\n",head.ri.hd.sl1.sh1.codec);
printf("flags: %d\n",head.ri.hd.sl1.sh1.flags);
printf("priority: %d\n",head.ri.hd.sl1.sh1.priority);
printf("language: %d\n",head.ri.hd.sl1.sh1.language);
printf("init_frame: %d\n",head.ri.hd.sl1.sh1.init_frames);
printf("scale: %d\n",head.ri.hd.sl1.sh1.scale);
printf("rate: %d\n",head.ri.hd.sl1.sh1.rate);
printf("start: %d\n",head.ri.hd.sl1.sh1.start);
printf("length: %d\n",head.ri.hd.sl1.sh1.length);
printf("suggest_buff_size: %d\n",head.ri.hd.sl1.sh1.suggest_buff_size);
printf("quality: %d\n",head.ri.hd.sl1.sh1.quality);
printf("sample_size: %d\n",head.ri.hd.sl1.sh1.sample_size);
printf("-----------audio strh--------------\n");
printf("ausio strh_id: %s\n",head.ri.hd.sl2.sh2.id);
printf("size: %d\n",head.ri.hd.sl2.sh2.size);
printf("stream_type: %s\n",head.ri.hd.sl2.sh2.stream_type);
printf("codes: %s\n",head.ri.hd.sl2.sh2.codec);
printf("flags: %d\n",head.ri.hd.sl2.sh2.flags);
printf("priority: %d\n",head.ri.hd.sl2.sh2.priority);
printf("language: %d\n",head.ri.hd.sl2.sh2.language);
printf("init_frame: %d\n",head.ri.hd.sl2.sh2.init_frames);
printf("scale: %d\n",head.ri.hd.sl2.sh2.scale);
printf("rate: %d\n",head.ri.hd.sl2.sh2.rate);
printf("start: %d\n",head.ri.hd.sl2.sh2.start);
printf("length: %d\n",head.ri.hd.sl2.sh2.length);
printf("suggest_buff_size: %d\n",head.ri.hd.sl2.sh2.suggest_buff_size);
printf("quality: %d\n",head.ri.hd.sl2.sh2.quality);
printf("sample_size: %d\n",head.ri.hd.sl2.sh2.sample_size);
printf("-----------audio strf--------------\n");
printf("audio strf:id %s\n",head.ri.hd.sl2.sf2.id);
printf("size: %d\n",head.ri.hd.sl2.sf2.size);
printf("波型格式 : %d\n",head.ri.hd.sl2.sf2.wFormatTag);
printf("nChannls: %d\n",head.ri.hd.sl2.sf2.nChannels);
printf("采样率 : %d\n",head.ri.hd.sl2.sf2.nSamplesPerSec);
printf("平均数率: %d\n",head.ri.hd.sl2.sf2.nAvgBytesPerSec);
printf("nMlockAlign: %d\n",head.ri.hd.sl2.sf2.nBlockAlign);
printf("采样位宽: %d\n",head.ri.hd.sl2.sf2.wBitsPerSample);
printf("biSize: %d\n",head.ri.hd.sl2.sf2.biSize);
return 0;
}以上就是C语言实现为无声avi视频添加wave音乐的详细内容,更多关于C语言视频添加音乐的资料请关注脚本之家其它相关文章!
