0%

前言

​ 在2021年1月12日之后,Flash将会无法运行,由于影响到了一些年老的系统的运行,所以要让Flash继续工作,经过一系列搜索,在百度贴吧找到了一个帖子,里面的方法可以让Flash继续工作。但是由于需要用WinHex修改文件,对电脑不熟悉的小白同事有一定难度,故有了写一个小工具的想法。

代码

Github : https://github.com/iamKyun/flash-on
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
package main

import (
"bytes"
"fmt"
"io/ioutil"
"os"
"os/exec"
)

/**
* 此代码只针对windows系统
*/
func main() {
// 获取操作系统位数
bit := 32 << (^uint(0) >> 63)
var filePath string
if bit == 64 {
filePath = "C:\\Windows\\SysWOW64\\Macromed\\Flash\\Flash.ocx"
} else {
filePath = "C:\\Windows\\System32\\Macromed\\Flash\\Flash.ocx"
}
fmt.Println("!!!运行前请关闭浏览器!!!")
fmt.Printf("%d位操作系统\n", bit)
fmt.Printf("读取文件:%s\n", filePath)
content, err := ioutil.ReadFile(filePath)
if err != nil {
fmt.Println("读取文件失败,请检查文件是否存在")
return
}
targetBytes := []byte{0x00, 0x00, 0x40, 0x46, 0x3E, 0x6F, 0x77, 0x42}
fmt.Println("开始查找目标代码...")
if bytes.Contains(content, targetBytes) {
fmt.Println("开始尝试修改...")
fmt.Println("获取文件权限...")
c := exec.Command("cmd", "/C", "TAKEOWN", "/F", filePath, "/a")
if err := c.Run(); err != nil {
fmt.Println("修改文件权限失败,请用管理员权限运行!")
return
}
c2 := exec.Command("cmd", "/C", "ICACLS", filePath, "/grant", "Administrators:F")
if err := c2.Run(); err != nil {
fmt.Println("修改文件权限失败,请用管理员权限运行!")
return
}
targetIndex := bytes.Index(content, targetBytes)
modifyIndex := targetIndex + 7
content[modifyIndex] = 0x72
err := ioutil.WriteFile(filePath, content, os.ModePerm)
if err == nil {
fmt.Println("修改成功,flash已被激活")
} else {
fmt.Println("修改失败,原因:")
fmt.Println(err)
}
} else {
fmt.Println("找不到目标代码,修改失败")
}

fmt.Print("\n按enter键退出...")
fmt.Scanln()
}

前言

文章由 https://www.iamkyun.com 翻译以下视频而成: https://www.youtube.com/watch?v=XvoW-bwIeyY

自数码视频在1988年问世,为了提升视频质量、减少文件大小和改善视频播放质量,几乎每年都会开发出新的视频格式 。视频的受欢迎程度持续快速增长,78%的人每天都会至少观看一个视频。然而,大多数人都不清楚视频播放背后的机理到底是怎样的。

以下内容将会告诉你关于视频的一些基础知识,和怎么利用它们达到你的目的。

接下来,你将会学习到:

  • 编码解码器(Codec)
  • 视频格式(Video Format)
  • 封装格式/容器(Container)

剧透一下:Video Format & Container 同义。编码解码器(Codec)对应的内容是编码格式。

在一般人的认知中,存在这一个常见的误区,那就是认为视频文件的后缀名就是视频的格式,但事实并不是那样的。

某些视频格式可能由一堆文件,文件夹,甚至播放列表组成,它们都是视频能够正常播放的必要元素。为了更清楚地了解视频格式,我们拿具体的一个视频文件来举例,来弄懂视频的各部分是怎样一起工作,让画面呈现在你的显示器上的。

1.png

视频文件的后缀实际上含义是“封装格式/容器(Container,后文称容器)”,容器里面包含了视频播放所需的各种文件,这些文件包括:

  • 视频流(Video Stream)
  • 音频流(Audio Stream)
  • 元数据(Meta Data)

视频流功能是告诉播放器,应该显示出什么样的画面。音频流的功能是告诉播放器,在视频播放过程中应该发出什么样的声音。元数据,也称为“描述数据的数据”,它里面包含了视频的信息,例如码率、分辨率、字幕、设备信息和制作时间等一些内容。

2.png

其中,元数据里面最重要的一部分就是编码解码器Codec,下文称Codec),如果你接触过一些视频相关的工作,那么你可能已经接触过它。

Codec(编码解码器)

Codec是一个复合单词,由Coder和Decoder组成。

3.png

Codec,顾名思义,它用来编码和解码视频、音频的。编码,也就是视频编辑工作中常说的“压制”,目的是让视频的体积减小,易于管理;解码,就是播放器或其他目标软件根据Codec里设定好的解码规则,经过解码器后,把被压缩的视频还原成和*原来质量相近(有损和无损压缩)*的视频,随后呈现到显示其中。

4.png

像视频格式一样,Codec也有很多种,每种编码格式都对应一种Codec,编码格式还分为视频编码格式音频编码格式,固Codec也有视频Codec音频Codec

5.png

我们拿几种流行的Codec,来了解一些它们的优势和劣势。

6.png

视频Codec

H.264

我们先看看H.264,也称Advanced Video Coding(AVC),H.264是目前为止使用得最普遍Codec,因为在相同文件大小情况下,它在码率方便做得比它的前代H.263更好,也是因为这样,H.264被广泛支持,在使用它的时候,你也不用怕遇到了问题而找不到解决方法。

7.png

H.265

H.264的下一代,H.265,也称High Efficiency Video Coding(HEVC),和它的名字一样,H.265的压缩率几乎是H.264的两倍,这意味着,用HEVC编码和用AVC编码的质量相同的一个视频,前者的的文件大小能比后者少一半,这也对2k以上的高分辨率视频来说是个好消息。但是如果用HEVC编码视频,要求也比一般的Codec高,几乎需消耗3倍的资源。

就像H.264一样,H.265是一个私有的Codec,在使用上是需要授权的。虽然HEVC在一直成长,但是到目前为止还不如它的前代流行。苹果公司在HEVC的支持上表也现得很活跃。但随着其他新的Codec被推出,HEVC的是否还具备优势也成了一个疑问。

8.png

VP9

VP9是一个由Google开发的开放格式、无需授权费的Codec。起初这个Codec是用在YouTube上的,像H.265一样,VP9的压缩率也能达到它的前代VP8的两倍,对高分辨率视频友好,但是在编码方面的环境要求颇高,支持度也没H.264广泛。

9.png

但是,VP9背后的技术通常使得流的一致性和可靠性提高,而H.265通常能提供更好的图像质量。同样重要的是,VP9通常使用WebMIVF容器,这里就不展开讲这两个容器了。

10.png

AV1

另一个开放、免授权的Codec,AV1(AOMedia Video 1),它开放媒体联盟开发,但现阶段还处于发展期,正逐渐被各大平台支持。

音频Codec

上面介绍的一些常见的视频Codec,但音频Codec又是另一回事了,而且它对视频也非常重要。让我们介绍一下一些常用的音频Codec,让你在使用中可以决定用哪个Codec来帮助你完成工作。

MP3

最著名的音频Codec要数MP3莫属了,它由动态影像专家小组(Moving Picture Experts Group,简称MPEG)在1993年开发出来。这种有损的Codec利用了人类的听力局限性(听觉掩蔽),从而达到即使有损,也对听觉体验不打折扣的目的。例如,MP3通常压制码率为128kbs,听起来就和CD播放器一样,但是文件大小只有CD的9%。现在,MP3已成为最流行的音频格式,但是,它在视频的应用上也有它功能局限性。

11.png

AAC

近些年,也有不少的音频Codec正发展起来。 例如,AAC(Advanced Audio Coding),是MP3出来不久后,就开发的音频专有Codec。AAC的主要好处就是有广泛的平台支持并且在相同的码率下的音频质量也比MP3更高,这使得AAC成为了视频中最流行的音频Codec。但是,AAC在音频通道(Audio Channels)中存在局限性,这意味着,如果我们想要得到一个更好的播放体验,就需要另外的Codec来支持了。

12.png

AC3

如果你需要环绕声或对Dolby产品向后兼容,AC3(Dolby Digital Audio Codec 3)是一个选择,因为它对音频通道有完整支持,但是对于DVD播放器或数字电视,AC3的支持度就不是那么好了。

13.png

Codec总览

尽管还有其他的一些音频、视频Codec,但以上介绍的已经是最常见最重要的了。

14.png

Video Format & Container (视频格式&容器)

知道了一些基础知识后,我们终于可以说一说视频文件格式(Video File Format)了。视频文件格式是一个标准化规则,用于存储视频文件的容器、Codec、元数据,有时甚至是文件夹结构,因此不同的设备和播放器才能轻松地支持它们。

自从第一个视频格式变得流行,几乎每年都会开发出新的视频格式,意图改善图像的质量、优化文件大小、提高播放质量和提供一些额外的特性。

当一个大平台决定在它产品中支持一个视频格式时,这个视频格式就会变得流行,通常是因为取得了一些技术突破或特殊用途。这常常会形成自我促进的循环:大平台的支持使创作者会用这个视频格式生产出更多内容,而其他平台看见有如此多与这个视频格式相关的内容后,也逐渐开始支持对这个视频格式。

在以下文章中,我们将会告诉你那些视频格式是最流行的和怎样选择它们。

首先,不同的视频格式在视频编辑网络内容分发上的流行程度都不一样。这是因为视频编辑通常需要更高质量的文件,而网络内容分发更注重更小文件体积更流畅的播放体验。而在本文中,更侧重在网络内容分发上。

15.png

MP4

我们第一个要说的格式是MP4,更具体应该指MPEG-4,更更具体应该称MPEG-4第14部分。因为MPEG-4这个名称很容易私人迷惑,因为不同的人叫MPEG-4时,所指的含义可能会不一样。常见的3种含义分别是:

  • MP4 容器(MPEG-4第14部分,我们正在讨论的是这个)

  • ISO Base Media File(MPEG-4第12部分,在视频流上用到)

  • H.264 Codec(MPEG-4第10部分,在视频压制上用到)

16.png

本文主要讨论的是视频格式,也就是上述第1种意思的同义。

MP4是一种对于Web程序输出视频友好的容器,因为它存在单独的一个容器中并且得到各种各样的设备和操作系统支持。

17.png

HLS

由于用户互联网网速的不可预测性和对直播的需求增加,近年来,一种叫“自适应码率片段(Adaptive Bitrate Segmentation)”的新视频技术正逐渐流行。

自适应码率(ABR)的工作原理是把视频流转换为不同的分辨率,并用不同的码率来分割成一堆小片段。

18.png

这些小片段能在用户不同网络状况下进行互相替换,达到流畅的播放体验的目的。

19.png

2009年,苹果公司开发出了HLS(HTTP Live Streaming),这个视频格式建立在自适应码率上,通过HTTP分发,并且广泛兼容多种设备和防火墙,很快就成为最流行的一种视频格式。

20.png

不像MP4,HLS其中最重要的一个文件是h3u8播放列表,作用是把各个视频片段组成一个完整的视频,其文件后缀名也是“.m3u8”。

21.png

MPEG-DASH

MPEG-DASH是另一个自适应码率的格式,由动态影像专家小组(MPEG)开发,和HLS类似,也是采用HTTP协议,其中不同的是,DASH是一个开源格式,并且它是国际标准,也是第一个具有国际标准的自适应流。

22.png

虽然HLS现在还是非常流行,但是DASH毫无意外地会很快赶上,因为它是无需授权费的。

以上就是全部内容,介绍了几种重要的视频格式/容器、视频Codec、音频Codec。

23.png

最后,附上在SDR、HDR下,不同分辨率和帧率的视频码率推荐。

24.png

实现方式参考官方配置文档官方LDAP实现

实现源码:https://github.com/iamKyun/flowable-examples/tree/master/example-1

实现代码

  1. 此实现的SpringBoot版本为2.3.0,Flowable版本为6.5,不同的版本可能实现不一样,但是最终目的都是要让我们自己的身份管理服务实现类去把Flow able自动配置的给替换掉。

  2. 实现接口:org.flowable.idm.api.IdmIdentityService,根据需求实现里面的查询器和查询方法

    1
    2
    3
    4
    5
    6
    7
    8
    // 这里直接继承了它的默认实现类
    public class CustomIdmIdentityServiceImpl extends IdmIdentityServiceImpl {
    @Override
    public UserQuery createUserQuery() {
    // 自定义的用户查询器实现
    return new CustomUserQueryImpl();
    }
    }
  3. 用Spring Bean的方式配置一个属于SpringIdmEngineConfiguration的引擎配置器,在配置器里设置IdmIdentityService的自定义实现

    1
    2
    3
    4
    5
    @Bean
    public EngineConfigurationConfigurer<SpringIdmEngineConfiguration> idmEngineConfigurationConfigurer() {
    return idmEngineConfiguration -> idmEngineConfiguration.setIdmIdentityService(
    new CustomIdmIdentityServiceImpl());
    }
  4. 测试

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    @SpringBootTest(classes = ExampleApplication.class)
    class ExampleApplicationTests {

    @Autowired
    private IdentityService identityService;

    @Test
    @FormDeploymentAnnotation
    public void identityServiceTest() {
    // 查询方法最终调用了 CustomUserQueryImpl,里面的测试数据有3个用户,对应ID:["1","2","3"]
    long result1 = identityService.createUserQuery().userId("1").count();
    long result2 = identityService.createUserQuery().userId("4").count();
    long result3 = identityService.createUserQuery().userIds(Arrays.asList("1", "2", "4")).count();
    Assertions.assertEquals(1, result1);
    Assertions.assertEquals(0, result2);
    Assertions.assertEquals(2, result3);
    }

    }

源码解析

org.flowable.engine.IdentityService执行查询的方法中,是代理给org.flowable.idm.api.IdmIdentityService去执行。

图1

此接口的实现只有1个org.flowable.idm.engine.impl.IdmIdentityServiceImpl

图2

查找调用处可以发现只有1处新建该类的对象 (org.flowable.idm.engine.IdmEngineConfiguration:100),所以最终的目的是:更改IdmEngineConfiguration的成员变量:idmIdentityService,让其变成我们自定义的IdmIdentityService (此处指上文的CustomIdmIdentityServiceImpl)。

图3

现在所处在的类是org.flowable.idm.engine.IdmEngineConfiguration,它是Flowable的IDM引擎配置类,在Spring环境下该类有一个子类名为:org.flowable.idm.spring.SpringIdmEngineConfiguration,而引入了flowable-spring-boot-starter之后,在SpringBoot的环境下,自动配置生效。使得SpringIdmEngineConfiguration自动成为一个Spring Bean。

图4

4-1

所以此时已经有一个方法了,只要改变此SpringIdmEngineConfiguration Bean的IdmIdentityService就可以替换IDM引擎。

4-2

这样也能达到目的,但是配置过于冗余,基本上是复制了一整段代码。

参考官方LDAP自动配置的实现,可以发现它只用一个Bean就完成了IdmIdentityService的替换,就是文章中一开始所展示的实现方式。

这种实现方式是怎么生效的呢?其中关键接口是org.flowable.spring.boot.EngineConfigurationConfigurer

由它的注释可以看到:

Interface to be implemented by a bean that does some extra configuration of a Flowable engines. If such a bean is defined, it will be called when the specific engine configuration is created and the default values have been set.

在Flowable引擎创建并设置好默认值时,这个接口是实现类会用来为这些Flowable引擎做一些额外的配置工作。

这个接口与IDM引擎关联的代码是在:org.flowable.spring.boot.idm.IdmEngineAutoConfiguration.IdmEngineAppConfiguration#idmEngineConfigurator

图5

SpringIdmEngineConfiguration 准备好时,它会调用invokeConfigurars()方法,让属于SpringIdmEngineConfiguration的配置器来为SpringIdmEngineConfiguration做一些额外的配置。

图6

最后,就调用到了我们文中一开始所定义的配置器Bean,让我们自定义的IDM服务生效。

图7

WSL

前言

​ 微软正在计划让WSL2支持基于RDP的GUI[1],虽然这一特性目前还不可用,但我们还是能通过别的一些手段来达到目的。

准备环境

安装工具

  1. 先把apt update & upgrade
1
sudo apt update && sudo apt -y upgrade
  1. 安装XRDP[2](远程连接协议)、Xfce[3](轻量级桌面环境,安装时会提示选择gdm3或lightdm,我选了gdm3)
1
2
3
4
sudo apt-get purge xrdp
sudo apt install -y xrdp
sudo apt install -y xfce4
sudo apt install -y xfce4-goodies
  • 非必须)更改XRDP的一些配置:增加bpp(bits per pixel),让远程连接质量更好
1
2
3
sudo sed -i 's/max_bpp=32/#max_bpp=32\nmax_bpp=128/g' /etc/xrdp/xrdp.ini
sudo sed -i 's/xserverbpp=24/#xserverbpp=24\nxserverbpp=128/g' /etc/xrdp/xrdp.ini
echo xfce4-session > ~/.xsession
  1. 接下来更改XRDP的启动脚本,让它同时启动Xfce
1
sudo vim /etc/xrdp/startwm.sh

​ 把文件的最后几行改成这样:

1
2
3
4
# test -x /etc/X11/Xsession && exec /etc/X11/Xsession
# exec /bin/sh /etc/X11/Xsession
# xfce
startxfce4

code

  1. 最后,启动XDRP
1
sudo /etc/init.d/xrdp start

开始使用

使用Windows的远程桌面连接,通过WSL的IP地址:33893389为默认端口,可以在配置/etc/xrdp/xrdp.ini中更改。

Windows远程桌面连接

用WSL的用户名和密码登录进系统

登陆界面

完成,最后成品:

Ubuntu桌面

后言

​ 此文章所使用的方法是通过一些手段来让WSL2支持GUI,所以在使用的过程中略有繁琐和有一些不太完美的地方。相信之后微软推出的WSL2 GUI特性将会很好地支持这方面的使用。想要持续关注这一方面的信息,可以到微软的开发者博客上关注这方面的内容。


  1. The Windows Subsystem for Linux BUILD 2020 Summary ↩︎

  2. Website of XRDP ↩︎

  3. Website of Xfce ↩︎