文章目录

  • 前言
  • 一、实现思路
  • 1.你需要把视频转换成一帧一帧的图片。
  • 2.把图片转换成字符串文件。
  • 3.按照一定的时间差遍历打印字符串文件。
  • 4.另起一个线程进行音乐的同步播放。
  • 二、具体步骤
  • 1.视频转图片
  • 2.图片转字符串文件
  • 3.循环遍历字符串文件
  • 4.通过异步线程添加音乐播放
  • 三、总结


前言

最近华强买瓜在B站大火,于是乎在闲暇之余,通过百度和各种学习,终于将这个视频通过Java形式展现出来了~
具体效果是这样的~
可以参考我发布在B站的视频进行预览~


华强买瓜【程序员复刻版】


一、实现思路

其实实现这个视频转文字输出的功能并不难,就是需要分成好几个环节去实现。

1.你需要把视频转换成一帧一帧的图片。

2.把图片转换成字符串文件。

3.按照一定的时间差遍历打印字符串文件。

4.另起一个线程进行音乐的同步播放。

二、具体步骤

首先准备好华强买瓜的原视频:
链接:https://pan.baidu.com/s/1HRAAzprVArxd692kUsKoPQ
提取码:p88i

1.视频转图片

通过AoaoPhoto Video to Picture Converter 将视频转换为图片。
软件下载地址:
视频转换工具

1)首先选择上面的load(视频导入目录)和下面的output folder(图片导出目录)

2)选择分辨率为1280*720,无效果,每秒十张图片,图片格式为PNG。

3)点击convert(转换)

操作如下图所示:

java 请求动画帧 java实现动画_java 请求动画帧

2.图片转字符串文件

通过Ascgen 2 批量将图片转换为字符串文件。

下载地址:图片转换字符串工具 1)选择批量转换

java 请求动画帧 java实现动画_华强买瓜_02

2)添加要转换的文件夹,以及转化后的文件夹位置,点击开始。

java 请求动画帧 java实现动画_华强买瓜字符动画实现_03

3.循环遍历字符串文件

接下来就到了代码的部分了~

long stime = System.currentTimeMillis();
//			File file = new File(Hua.class.getClassLoader().getResource("input").getPath());
		File file = new File("E:\\picture\\output\\OutputStrs");
			File[] files = file.listFiles();
			for (int i = 0; i < files.length; i++) {
				 BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream(files[i])));
				 String line ="";
				 String str = null;
			        while ((str = in.readLine()) != null) {
			           line += str+"\n";
			        }
			        System.out.println(line);
			        Thread.sleep(5);//打印的间隔时间
			        line = "";
			        //打印一张清空屏幕内容
			        new ProcessBuilder("cmd", "/c", "cls").inheritIO().start().waitFor();
			        in.close();
			}
		long etime = System.currentTimeMillis();
		System.out.println("播放时长:"+(etime-stime)/1000);

4.通过异步线程添加音乐播放

1)音频转换:
音乐可以通过绘声绘影将MP4转换为音频。
转换教程:绘声绘影转换视频为音频 如果懒得转换,直接使用下面资源:
链接:https://pan.baidu.com/s/1cbFR4l9TOb7wJGJxvc5Bpw
提取码:77dd

2)音乐播放的相关代码:

public static void playMusic() throws Exception, IOException{
		//1 获取你要播放的音乐文件
//		File files = new File(Hua.class.getClassLoader().getResource("music").getPath());
//		File file = files.listFiles()[0];
		File file = new File("E:\\picture\\华强买瓜.wav");
		//2、定义一个AudioInputStream用于接收输入的音频数据
		AudioInputStream am;
		//3、使用AudioSystem来获取音频的音频输入流(处理(抛出)异常)
		am = AudioSystem.getAudioInputStream(file);
		//4、使用AudioFormat来获取AudioInputStream的格式
		AudioFormat af = am.getFormat();
		//5、一个源数据行
		SourceDataLine sd ;
		//6、获取受数据行支持的音频格式DataLine.info
		//DataLine.Info dl = new DataLine.Info(SourceDataLine.class, af);
		//7、获取与上面类型相匹配的行 写到源数据行里 二选一
		sd = AudioSystem.getSourceDataLine(af);//便捷写法
		//sd = (SourceDataLine) AudioSystem.getLine(dl);
		//8、打开具有指定格式的行,这样可以使行获得资源并进行操作
		sd.open();
		//9、允许某个数据行执行数据i/o
		sd.start();
		//10、写数据
		int sumByteRead = 0; //读取的总字节数
		byte [] b = new byte[320];//设置字节数组大小
		//11、从音频流读取指定的最大数量的数据字节,并将其放入给定的字节数组中。
		while (sumByteRead != -1) {//-1代表没有 不等于-1时就无限读取
			sumByteRead = am.read(b, 0, b.length);//12、读取哪个数组
			if(sumByteRead >= 0 ) {//13、读取了之后将数据写入混频器,开始播放
				sd.write(b, 0, b.length);
				
			}
		}
		//关闭
		sd.drain();
		sd.close();
	}

3)异步线程:

思路其实就是把播放音乐的方法写在线程的run方法中,然后在打印直接就启动线程。
由于我这边直接将内容都写在一起了,并没有很好的规划代码结构。直接将完整源码贴在下面。

public class Hua extends Thread{

	public static void main(String[] args) throws Exception {
		new Hua().start();
		long stime = System.currentTimeMillis();
//			File file = new File(Hua.class.getClassLoader().getResource("input").getPath());
		File file = new File("E:\\picture\\output\\OutputStrs");
			File[] files = file.listFiles();
			for (int i = 0; i < files.length; i++) {
				 BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream(files[i])));
				 String line ="";
				 String str = null;
			        while ((str = in.readLine()) != null) {
			           line += str+"\n";
			        }
			        System.out.println(line);
			        Thread.sleep(5);
			        line = "";
			        new ProcessBuilder("cmd", "/c", "cls").inheritIO().start().waitFor();
			        in.close();
			}
		long etime = System.currentTimeMillis();
		System.out.println("播放时长:"+(etime-stime)/1000);
	}

	@Override
	public void run() {
		try {
			playMusic();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	
	public static void playMusic() throws Exception, IOException{
		//1 获取你要播放的音乐文件
//		File files = new File(Hua.class.getClassLoader().getResource("music").getPath());
//		File file = files.listFiles()[0];
		File file = new File("E:\\picture\\华强买瓜.wav");
		//2、定义一个AudioInputStream用于接收输入的音频数据
		AudioInputStream am;
		//3、使用AudioSystem来获取音频的音频输入流(处理(抛出)异常)
		am = AudioSystem.getAudioInputStream(file);
		//4、使用AudioFormat来获取AudioInputStream的格式
		AudioFormat af = am.getFormat();
		//5、一个源数据行
		SourceDataLine sd ;
		//6、获取受数据行支持的音频格式DataLine.info
		//DataLine.Info dl = new DataLine.Info(SourceDataLine.class, af);
		//7、获取与上面类型相匹配的行 写到源数据行里 二选一
		sd = AudioSystem.getSourceDataLine(af);//便捷写法
		//sd = (SourceDataLine) AudioSystem.getLine(dl);
		//8、打开具有指定格式的行,这样可以使行获得资源并进行操作
		sd.open();
		//9、允许某个数据行执行数据i/o
		sd.start();
		//10、写数据
		int sumByteRead = 0; //读取的总字节数
		byte [] b = new byte[320];//设置字节数组大小
		//11、从音频流读取指定的最大数量的数据字节,并将其放入给定的字节数组中。
		while (sumByteRead != -1) {//-1代表没有 不等于-1时就无限读取
			sumByteRead = am.read(b, 0, b.length);//12、读取哪个数组
			if(sumByteRead >= 0 ) {//13、读取了之后将数据写入混频器,开始播放
				sd.write(b, 0, b.length);
				
			}
		}
		//关闭
		sd.drain();
		sd.close();
	}
	
}

4)运行及打包:

java 请求动画帧 java实现动画_华强买瓜_04

打包时右键项目选择export

java 请求动画帧 java实现动画_华强买瓜_05

选择jar file

java 请求动画帧 java实现动画_Java_06

选择jar包存放位置,以及起一个名称。

java 请求动画帧 java实现动画_Java_07

点击下一步-下一步,选择主函数所在的类。

java 请求动画帧 java实现动画_java 请求动画帧_08

点击完成,即可导出可执行jar包。

java 请求动画帧 java实现动画_java 请求动画帧_09


然后打开cmd,在程序所在位置 java -jar jar包名称即可运行~~

java 请求动画帧 java实现动画_Java字符动画_10


java 请求动画帧 java实现动画_Java字符动画_11

当然,你可以微调线程休眠时间(Thread.sleep(5);)来优化音乐播放和打印时的偏差,达到同步~

三、总结

通过这篇文章你可以实现各种基于视频的字符动画打印,发挥你的创意,创造更多好的作品吧~~