diff --git a/Cargo.lock b/Cargo.lock
index ecf356e..7838334 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -791,70 +791,6 @@ version = "1.6.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
 
-[[package]]
-name = "encoding"
-version = "0.2.33"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6b0d943856b990d12d3b55b359144ff341533e516d94098b1d3fc1ac666d36ec"
-dependencies = [
- "encoding-index-japanese",
- "encoding-index-korean",
- "encoding-index-simpchinese",
- "encoding-index-singlebyte",
- "encoding-index-tradchinese",
-]
-
-[[package]]
-name = "encoding-index-japanese"
-version = "1.20141219.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "04e8b2ff42e9a05335dbf8b5c6f7567e5591d0d916ccef4e0b1710d32a0d0c91"
-dependencies = [
- "encoding_index_tests",
-]
-
-[[package]]
-name = "encoding-index-korean"
-version = "1.20141219.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4dc33fb8e6bcba213fe2f14275f0963fd16f0a02c878e3095ecfdf5bee529d81"
-dependencies = [
- "encoding_index_tests",
-]
-
-[[package]]
-name = "encoding-index-simpchinese"
-version = "1.20141219.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d87a7194909b9118fc707194baa434a4e3b0fb6a5a757c73c3adb07aa25031f7"
-dependencies = [
- "encoding_index_tests",
-]
-
-[[package]]
-name = "encoding-index-singlebyte"
-version = "1.20141219.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3351d5acffb224af9ca265f435b859c7c01537c0849754d3db3fdf2bfe2ae84a"
-dependencies = [
- "encoding_index_tests",
-]
-
-[[package]]
-name = "encoding-index-tradchinese"
-version = "1.20141219.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fd0e20d5688ce3cab59eb3ef3a2083a5c77bf496cb798dc6fcdb75f323890c18"
-dependencies = [
- "encoding_index_tests",
-]
-
-[[package]]
-name = "encoding_index_tests"
-version = "0.1.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a246d82be1c9d791c5dfde9a2bd045fc3cbba3fa2b11ad558f27d01712f00569"
-
 [[package]]
 name = "encoding_rs"
 version = "0.8.26"
@@ -1224,15 +1160,13 @@ checksum = "cd179ae861f0c2e53da70d892f5f3029f9594be0c41dc5269cd371691b1dc2f9"
 
 [[package]]
 name = "id3"
-version = "0.5.1"
+version = "0.6.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "02c11bb50ce1568516aefbe4b6564c3feaf15a8e5ccbea90fa652012446ae9bf"
+checksum = "f23fa956cb2f3e3e547993eb62b6f76b5babd86c3e7bb4fe1149ef192d90df51"
 dependencies = [
  "bitflags",
  "byteorder",
- "encoding",
  "flate2",
- "lazy_static",
 ]
 
 [[package]]
diff --git a/Cargo.toml b/Cargo.toml
index 35c982a..20caa2b 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -24,7 +24,7 @@ diesel_migrations = { version = "1.4", features = ["sqlite"] }
 futures-util = { version = "0.3" }
 getopts = "0.2.15"
 http = "0.2.2"
-id3 = "0.5.1"
+id3 = "0.6.3"
 libsqlite3-sys = { version = "0.18", features = ["bundled", "bundled-windows"], optional = true }
 lewton = "0.10.1"
 log = "0.4.5"
diff --git a/src/app/index/metadata.rs b/src/app/index/metadata.rs
index 6177ffb..9751548 100644
--- a/src/app/index/metadata.rs
+++ b/src/app/index/metadata.rs
@@ -27,15 +27,46 @@ pub struct SongTags {
 	pub has_artwork: bool,
 }
 
+impl From<id3::Tag> for SongTags {
+	fn from(tag: id3::Tag) -> Self {
+		let artist = tag.artist().map(|s| s.to_string());
+		let album_artist = tag.album_artist().map(|s| s.to_string());
+		let album = tag.album().map(|s| s.to_string());
+		let title = tag.title().map(|s| s.to_string());
+		let duration = tag.duration();
+		let disc_number = tag.disc();
+		let track_number = tag.track();
+		let year = tag
+			.year()
+			.map(|y| y as i32)
+			.or_else(|| tag.date_released().map(|d| d.year))
+			.or_else(|| tag.date_recorded().map(|d| d.year));
+		let has_artwork = tag.pictures().count() > 0;
+
+		SongTags {
+			artist,
+			album_artist,
+			album,
+			title,
+			duration,
+			disc_number,
+			track_number,
+			year,
+			has_artwork,
+		}
+	}
+}
+
 pub fn read(path: &Path) -> Option<SongTags> {
 	let data = match utils::get_audio_format(path) {
 		Some(AudioFormat::APE) => Some(read_ape(path)),
 		Some(AudioFormat::FLAC) => Some(read_flac(path)),
-		Some(AudioFormat::MP3) => Some(read_id3(path)),
+		Some(AudioFormat::MP3) => Some(read_mp3(path)),
 		Some(AudioFormat::MP4) => Some(read_mp4(path)),
 		Some(AudioFormat::MPC) => Some(read_ape(path)),
 		Some(AudioFormat::OGG) => Some(read_vorbis(path)),
 		Some(AudioFormat::OPUS) => Some(read_opus(path)),
+		Some(AudioFormat::WAVE) => Some(read_wave(path)),
 		None => None,
 	};
 	match data {
@@ -48,49 +79,35 @@ pub fn read(path: &Path) -> Option<SongTags> {
 	}
 }
 
-fn read_id3(path: &Path) -> Result<SongTags> {
-	let tag = {
-		match id3::Tag::read_from_path(&path) {
-			Ok(t) => Ok(t),
-			Err(e) => {
-				if let Some(t) = e.partial_tag {
-					Ok(t)
-				} else {
-					Err(e)
-				}
-			}
-		}?
-	};
+fn read_mp3(path: &Path) -> Result<SongTags> {
+	let tag = id3::Tag::read_from_path(&path).or_else(|error| {
+		if let Some(tag) = error.partial_tag {
+			Ok(tag)
+		} else {
+			Err(error)
+		}
+	})?;
+
 	let duration = {
 		mp3_duration::from_path(&path)
 			.map(|d| d.as_secs() as u32)
 			.ok()
 	};
 
-	let artist = tag.artist().map(|s| s.to_string());
-	let album_artist = tag.album_artist().map(|s| s.to_string());
-	let album = tag.album().map(|s| s.to_string());
-	let title = tag.title().map(|s| s.to_string());
-	let disc_number = tag.disc();
-	let track_number = tag.track();
-	let year = tag
-		.year()
-		.map(|y| y as i32)
-		.or_else(|| tag.date_released().and_then(|d| Some(d.year)))
-		.or_else(|| tag.date_recorded().and_then(|d| Some(d.year)));
-	let has_artwork = tag.pictures().count() > 0;
+	let mut song_tags: SongTags = tag.into();
+	song_tags.duration = duration; // Use duration from mp3_duration instead of from tags.
+	Ok(song_tags)
+}
 
-	Ok(SongTags {
-		artist,
-		album_artist,
-		album,
-		title,
-		duration,
-		disc_number,
-		track_number,
-		year,
-		has_artwork,
-	})
+fn read_wave(path: &Path) -> Result<SongTags> {
+	let tag = id3::Tag::read_from_wav(&path).or_else(|error| {
+		if let Some(tag) = error.partial_tag {
+			Ok(tag)
+		} else {
+			Err(error)
+		}
+	})?;
+	Ok(tag.into())
 }
 
 fn read_ape_string(item: &ape::Item) -> Option<String> {
@@ -306,6 +323,10 @@ fn reads_file_metadata() {
 		read(Path::new("test-data/formats/sample.ape")).unwrap(),
 		sample_tags
 	);
+	assert_eq!(
+		read(Path::new("test-data/formats/sample.wav")).unwrap(),
+		sample_tags
+	);
 }
 
 #[test]
@@ -325,4 +346,9 @@ fn reads_embedded_artwork() {
 			.unwrap()
 			.has_artwork
 	);
+	assert!(
+		read(Path::new("test-data/artwork/sample.wav"))
+			.unwrap()
+			.has_artwork
+	);
 }
diff --git a/src/app/thumbnail/read.rs b/src/app/thumbnail/read.rs
index e518704..d2470d5 100644
--- a/src/app/thumbnail/read.rs
+++ b/src/app/thumbnail/read.rs
@@ -9,11 +9,12 @@ pub fn read(image_path: &Path) -> Result<DynamicImage> {
 	match utils::get_audio_format(image_path) {
 		Some(AudioFormat::APE) => read_ape(image_path),
 		Some(AudioFormat::FLAC) => read_flac(image_path),
-		Some(AudioFormat::MP3) => read_id3(image_path),
+		Some(AudioFormat::MP3) => read_mp3(image_path),
 		Some(AudioFormat::MP4) => read_mp4(image_path),
 		Some(AudioFormat::MPC) => read_ape(image_path),
 		Some(AudioFormat::OGG) => read_vorbis(image_path),
 		Some(AudioFormat::OPUS) => read_opus(image_path),
+		Some(AudioFormat::WAVE) => read_wave(image_path),
 		None => Ok(image::open(image_path)?),
 	}
 }
@@ -37,9 +38,19 @@ fn read_flac(path: &Path) -> Result<DynamicImage> {
 	)))
 }
 
-fn read_id3(path: &Path) -> Result<DynamicImage> {
+fn read_mp3(path: &Path) -> Result<DynamicImage> {
 	let tag = id3::Tag::read_from_path(path)?;
 
+	read_id3(&path, &tag)
+}
+
+fn read_wave(path: &Path) -> Result<DynamicImage> {
+	let tag = id3::Tag::read_from_wav(path)?;
+
+	read_id3(&path, &tag)
+}
+
+fn read_id3(path: &Path, tag: &id3::Tag) -> Result<DynamicImage> {
 	if let Some(p) = tag.pictures().next() {
 		return Ok(image::load_from_memory(&p.data)?);
 	}
@@ -117,4 +128,9 @@ fn can_read_artwork_data() {
 		.map(|d| d.to_rgb8())
 		.ok();
 	assert_eq!(opus_img, None);
+
+	let wave_img = read(Path::new("test-data/artwork/sample.wav"))
+		.unwrap()
+		.to_rgb8();
+	assert_eq!(wave_img, embedded_img);
 }
diff --git a/src/utils.rs b/src/utils.rs
index e5f1bb7..d745db2 100644
--- a/src/utils.rs
+++ b/src/utils.rs
@@ -21,6 +21,7 @@ pub enum AudioFormat {
 	MPC,
 	OGG,
 	OPUS,
+	WAVE,
 }
 
 pub fn get_audio_format(path: &Path) -> Option<AudioFormat> {
@@ -40,6 +41,7 @@ pub fn get_audio_format(path: &Path) -> Option<AudioFormat> {
 		"mpc" => Some(AudioFormat::MPC),
 		"ogg" => Some(AudioFormat::OGG),
 		"opus" => Some(AudioFormat::OPUS),
+		"wav" => Some(AudioFormat::WAVE),
 		_ => None,
 	}
 }
@@ -51,4 +53,8 @@ fn can_guess_audio_format() {
 		get_audio_format(Path::new("animals/🐷/my🐖file.flac")),
 		Some(AudioFormat::FLAC)
 	);
+	assert_eq!(
+		get_audio_format(Path::new("animals/🐷/my🐖file.wav")),
+		Some(AudioFormat::WAVE)
+	);
 }
diff --git a/test-data/artwork/sample.wav b/test-data/artwork/sample.wav
new file mode 100644
index 0000000..a59b8c1
Binary files /dev/null and b/test-data/artwork/sample.wav differ
diff --git a/test-data/formats/sample.wav b/test-data/formats/sample.wav
new file mode 100644
index 0000000..a323479
Binary files /dev/null and b/test-data/formats/sample.wav differ